{"record":{"id":"5a634a5d45474ac6","repo":"hashicorp/terraform","slug":"failed-to-open-state-file-at-v-v","errorCode":null,"errorMessage":"Failed to open state file at %v: %v","messagePattern":"Failed to open state file at (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/client.go","lineNumber":40,"sourceCode":"// blobs representing state.\n// Implements \"state/remote\".ClientLocker\ntype remoteClient struct {\n\tstorageClient *storage.Client\n\tbucketName    string\n\tstateFilePath string\n\tlockFilePath  string\n\tencryptionKey []byte\n\tkmsKeyName    string\n}\n\nfunc (c *remoteClient) Get() (payload *remote.Payload, diags tfdiags.Diagnostics) {\n\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}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/gcs/client.go#L22-L58","documentation":"remoteClient.Get() opens the state object via NewReader; if the error is anything other than storage.ErrObjectNotExist (which is treated as 'no state yet' and returns nil cleanly), it is surfaced here with the gs:// URL. ErrObjectNotExist does NOT produce this error.","triggerScenarios":"Reading state when the bucket exists but the object is unreadable: CSEK mismatch (the stored object was encrypted with a different key than the backend's encryption_key), permission denied on the specific object, transient read error, or a bucket-level access issue scoped to that key.","commonSituations":"encryption_key changed since the state was last written (most common — produces 'no decryption key was provided'); SA lacks storage.objects.get on the prefix; object archived to a colder storage with restore needed; transient GCS read error.","solutions":["If using CSEK, restore the original encryption_key (the one the state was written with) in the backend block and retry.","Check the %v: a 403 means IAM on that object; a key error means CSEK mismatch; a 5xx means retry.","Grant the SA 'roles/storage.objectViewer' (or objectAdmin) on the bucket/prefix.","Verify the object with 'gsutil cat gs://<bucket>/<prefix>/<ws>.tfstate' using the same credentials."],"exampleFix":"// before\nencryption_key = file(\"new-key.b64\")   // state was written with old-key\n\n// after\nencryption_key = file(\"old-key.b64\")   // restore the key used to write the state\nterraform init && terraform state pull","handlingStrategy":"try-catch","validationCode":"// Confirm readability with the same key before terraform\nctx := context.Background()\n_, err := client.Bucket(bucket).Object(prefix+\"/default.tfstate\").Key(csek).NewReader(ctx)\nif err != nil && err != storage.ErrObjectNotExist { log.Fatal(err) }","typeGuard":null,"tryCatchPattern":"payload, diags := client.Get()\nif diags.HasErrors() && strings.Contains(diags.Err().Error(), \"Failed to open state file\") {\n    // likely CSEK mismatch: prompt for the original encryption_key\n}","preventionTips":["Store the CSEK in a secret manager keyed to the same identifier as the bucket.","Document which key wrote which state version.","Never change encryption_key without a migration plan."],"tags":["gcs","gcp","state","csek","encryption","iam"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}