{"record":{"id":"4ba763422d441f44","repo":"hashicorp/terraform","slug":"object-q-is-empty","errorCode":null,"errorMessage":"object %q is empty","messagePattern":"object %q is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/oci/client.go","lineNumber":123,"sourceCode":"\tcontentArray, err := io.ReadAll(getResponse.Content)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to read 'content' from response: %w\", err)\n\t}\n\n\t// Compute MD5 hash\n\tmd5Hash := getResponse.ContentMd5\n\tif md5Hash == nil || len(*md5Hash) == 0 {\n\t\tmd5Hash = getResponse.OpcMultipartMd5\n\t}\n\t// Construct payload\n\tpayload := &remote.Payload{\n\t\tData: contentArray,\n\t\tMD5:  []byte(*md5Hash),\n\t}\n\n\t// Return an error instead of `nil, nil` if the object is empty\n\tif len(payload.Data) == 0 {\n\t\treturn nil, fmt.Errorf(\"object %q is empty\", c.path)\n\t}\n\n\treturn payload, nil\n}\n\nfunc (c *RemoteClient) Put(data []byte) tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\n\tlogger := logWithOperation(\"upload-state-file\").Named(c.path)\n\tctx := context.WithValue(context.Background(), \"logger\", logger)\n\tdataSize := int64(len(data))\n\tsum := md5.Sum(data)\n\tvar err error\n\tif dataSize > DefaultFilePartSize {\n\t\tlogger.Info(\"Using Multipart Feature\")\n\t\tvar multipartUploadData = MultipartUploadData{\n\t\t\tclient: c,\n\t\t\tData:   data,","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/oci/client.go#L105-L141","documentation":"Raised in getObject when GetObject and the body read both succeeded but the resulting payload has zero bytes (len(payload.Data) == 0). The comment at client.go:121 explicitly notes this replaces a prior 'nil, nil' that silently returned an empty state, so an empty-but-existing object is now treated as a corruption error rather than a fresh init.","triggerScenarios":"The state object at c.path exists (HeadObject did not 404) and GetObject returned HTTP 200, but the object body is empty. Reachable when something wrote a 0-byte object to the state key: a botched upload, an aborted multipart upload that left a 0-byte object, or an external process truncating the object.","commonSituations":"A previous 'terraform apply' crashed during upload leaving a 0-byte tfstate; someone manually emptied the object; a migration/import tool created the key without content; an aborted multipart commit leaving a placeholder object.","solutions":["List object versions: 'oci os object list-versions --bucket-name <b> --namespace <ns> --prefix <key>'; if versioning is on, restore the last non-empty version.","If you have a known-good backup, re-upload it (oci os object put) to the same key, or delete the 0-byte object and run 'terraform init' to let Terraform treat the state as absent.","Audit who/what wrote the 0-byte object via the OCI audit log around the object's last-modified time.","If the empty object is unexpected on a fresh backend, confirm no other pipeline shares the same key and overwrote it with empty content."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// After a successful Get, validate payload before trusting it as state:\npayload, err := c.getObject(ctx)\nif err == nil && len(payload.Data) == 0 {\n    return nil, fmt.Errorf(\"object %q is empty\", c.path) // (this is what the lib now does)\n}","typeGuard":null,"tryCatchPattern":"if len(payload.Data) == 0 {\n    return nil, fmt.Errorf(\"object %q is empty\", c.path)\n}","preventionTips":["Never let a 0-byte object land on the state key (it later trips this read error).","Enable object versioning so a corrupted/empty object can be rolled back.","Audit writes to the state key via OCI audit logs."],"tags":["oci","object-storage","empty-object","data-integrity","corruption","terraform-state"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}