{"record":{"id":"55936ae3b16545a1","repo":"hashicorp/terraform","slug":"failed-to-open-file-at-v-checksum-s-invalid","errorCode":null,"errorMessage":"failed to open file at %v: checksum %s invalid","messagePattern":"failed to open file at (.+?): checksum (.+?) invalid","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/cos/client.go","lineNumber":204,"sourceCode":"\t\terr = fmt.Errorf(\"failed to open file at %v: %v\", cosFile, err)\n\t\treturn\n\t}\n\tdefer rsp.Body.Close()\n\n\tlog.Printf(\"[DEBUG] getObject %s: code: %d, error: %v\", cosFile, rsp.StatusCode, err)\n\tif err != nil {\n\t\tif rsp.StatusCode == 404 {\n\t\t\terr = nil\n\t\t} else {\n\t\t\terr = fmt.Errorf(\"failed to open file at %v: %v\", cosFile, err)\n\t\t}\n\t\treturn\n\t}\n\n\tchecksum = rsp.Header.Get(\"X-Cos-Meta-Md5\")\n\tlog.Printf(\"[DEBUG] getObject %s: checksum: %s\", cosFile, checksum)\n\tif len(checksum) != 32 {\n\t\terr = fmt.Errorf(\"failed to open file at %v: checksum %s invalid\", cosFile, checksum)\n\t\treturn\n\t}\n\n\texists = true\n\tdata, err = ioutil.ReadAll(rsp.Body)\n\tlog.Printf(\"[DEBUG] getObject %s: data length: %d\", cosFile, len(data))\n\tif err != nil {\n\t\terr = fmt.Errorf(\"failed to open file at %v: %v\", cosFile, err)\n\t\treturn\n\t}\n\n\tcheck := fmt.Sprintf(\"%x\", md5.Sum(data))\n\tlog.Printf(\"[DEBUG] getObject %s: check: %s\", cosFile, check)\n\tif check != checksum {\n\t\terr = fmt.Errorf(\"failed to open file at %v: checksum mismatch, %s != %s\", cosFile, check, checksum)\n\t\treturn\n\t}\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/cos/client.go#L186-L222","documentation":"Raised by getObject() in the Tencent COS remote-state client when the downloaded object's 'X-Cos-Meta-Md5' header is missing or malformed. The client requires this custom metadata to be exactly a 32-character hex MD5 digest; if it is absent or the wrong length the object is treated as unreadable because its integrity cannot be verified. This guard exists because Terraform state is critical infrastructure state, so the backend refuses to trust an object whose provenance checksum was never recorded.","triggerScenarios":"The state/lock object exists in COS but was uploaded by an external tool, a different (older) backend version, or a manual process that did not set the 'X-Cos-Meta-Md5' custom header. Triggered on every Get()/Lock()/lockInfo() call that successfully downloads the object (HTTP 200) but then sees len(checksum) != 32 at client.go:203.","commonSituations":"State file was hand-uploaded with the Tencent console or coscli without metadata; migrating from another backend and the object was copied without preserving custom headers; a bug in an older terraform-provider-tencentcloud that omitted the header on writes; the object was written by a non-Terraform pipeline.","solutions":["Re-write the state object through Terraform itself (terraform plan/apply with the COS backend) so the 'X-Cos-Meta-Md5' header is set correctly, or run 'terraform state push' against the backend.","If migrating from another backend, use 'terraform state pull' on the source, then 'terraform state push --force' on the COS target so the new backend writes the object with correct metadata.","Inspect the object metadata in the Tencent COS console/coscli to confirm the X-Cos-Meta-Md5 header is present and is a 32-char hex string; if a manual upload, re-upload with the header set to the md5 hex of the file.","Remove the stale object and let Terraform recreate it on the next write if no live state needs preserving."],"exampleFix":"# before: object uploaded without metadata\ncoscli cp terraform.tfstate cos://my-bucket/terraform/state/default.tfstate\n\n# after: upload preserving/setting the X-Cos-Meta-Md5 header (md5 hex)\nMD5=$(md5sum terraform.tfstate | awk '{print $1}')\ncoscli cp --add-header X-Cos-Meta-Md5:$MD5 terraform.tfstate cos://my-bucket/terraform/state/default.tfstate\n\n# preferred: let terraform write it natively\nterraform init && terraform state push --force terraform.tfstate","handlingStrategy":"validation","validationCode":"// Before relying on a remote object, verify it carries the expected metadata.\n// (caller-side preflight, e.g. in a state-migration helper)\nfunc hasCOSMd5Meta(ctx context.Context, c *cos.Client, bucket, key string) (bool, error) {\n    _, err := c.Object.GetMetaData(ctx, key, nil)\n    if err != nil { return false, err }\n    // ensure X-Cos-Meta-Md5 is present and 32 hex chars\n    h := \"\" // read from ObjectHead response header X-Cos-Meta-Md5\n    return len(h) == 32 && isHex(h), nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write state/lock objects through the COS backend itself so the X-Cos-Meta-Md5 header is set.","When migrating state, use 'terraform state push' rather than copying objects out-of-band.","If you must upload manually, compute md5 and set X-Cos-Meta-Md5 to the 32-char hex digest."],"tags":["cos","tencent-cloud","checksum","metadata","state","data-integrity"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}