{"record":{"id":"f1c6cf44f2b4f115","repo":"hashicorp/terraform","slug":"failed-to-read-state-file-attrs-from-v-v","errorCode":null,"errorMessage":"Failed to read state file attrs from %v: %v","messagePattern":"Failed to read state file attrs from (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/client.go","lineNumber":52,"sourceCode":"\tctx := context.TODO()\n\tstateFileReader, err := c.stateFile().NewReader(ctx)\n\tif err != nil {\n\t\tif err == storage.ErrObjectNotExist {\n\t\t\treturn nil, diags\n\t\t} else {\n\t\t\treturn nil, diags.Append(fmt.Errorf(\"Failed to open state file at %v: %v\", c.stateFileURL(), err))\n\t\t}\n\t}\n\tdefer stateFileReader.Close()\n\n\tstateFileContents, err := ioutil.ReadAll(stateFileReader)\n\tif err != nil {\n\t\treturn nil, diags.Append(fmt.Errorf(\"Failed to read state file from %v: %v\", c.stateFileURL(), err))\n\t}\n\n\tstateFileAttrs, err := c.stateFile().Attrs(ctx)\n\tif err != nil {\n\t\treturn nil, diags.Append(fmt.Errorf(\"Failed to read state file attrs from %v: %v\", c.stateFileURL(), err))\n\t}\n\n\tresult := &remote.Payload{\n\t\tData: stateFileContents,\n\t\tMD5:  stateFileAttrs.MD5,\n\t}\n\n\treturn result, diags\n}\n\nfunc (c *remoteClient) Put(data []byte) tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\tctx := context.TODO()\n\terr := func() error {\n\t\tstateFileWriter := c.stateFile().NewWriter(ctx)\n\t\tif len(c.kmsKeyName) > 0 {\n\t\t\tstateFileWriter.KMSKeyName = c.kmsKeyName\n\t\t}","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/gcs/client.go#L34-L70","documentation":"After reading the state body, Get() calls stateFile().Attrs(ctx) to fetch object metadata (specifically the MD5 for the remote.Payload). If that metadata call fails, the read is considered failed and surfaced here. The body succeeded but the attributes RPC did not.","triggerScenarios":"The object was deleted between the NewReader and Attrs calls; transient GCS metadata API failure; IAM allows get object body but not get metadata (rare misconfiguration); object lock/hold returning attrs error.","commonSituations":"Race with another process deleting the state; transient GCS 5xx on the GET-metadata RPC; eventual-consistency surprise.","solutions":["Retry the terraform command; Attrs failures are usually transient.","If persistent, check 'gsutil stat gs://<bucket>/<prefix>/<ws>.tfstate' to confirm the object still exists and metadata is readable.","Investigate concurrent state deletion or a competing CI job writing/deleting the same workspace.","Ensure the SA has 'storage.objects.get' which covers both body and metadata."],"exampleFix":"# recover\nterraform state pull   # retry\ngsutil stat gs://bucket/prefix/default.tfstate   # confirm metadata readable","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n    _, diags := client.Get()\n    if !diags.HasErrors() { break }\n    if !strings.Contains(diags.Err().Error(), \"attrs\") { break }\n    time.Sleep(backoff(attempt))\n}","preventionTips":["Avoid concurrent delete/refresh on the same workspace.","Retry transient Attrs failures.","Ensure SA has storage.objects.get (covers both body and metadata)."],"tags":["gcs","gcp","state","metadata","network"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}