{"record":{"id":"aed02b995e739bf2","repo":"hashicorp/terraform","slug":"error-loading-encryption-key-s","errorCode":null,"errorMessage":"Error loading encryption key: %s","messagePattern":"Error loading encryption key: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/backend.go","lineNumber":268,"sourceCode":"\t\tendpoint := option.WithEndpoint(storageEndpoint)\n\t\topts = append(opts, endpoint)\n\t}\n\tclient, err := storage.NewClient(ctx, opts...)\n\tif err != nil {\n\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\tfmt.Errorf(\"storage.NewClient() failed: %v\", err),\n\t\t)\n\t}\n\n\tb.storageClient = client\n\n\t// Customer-supplied encryption\n\tkey := data.String(\"encryption_key\")\n\tif key != \"\" {\n\t\tkc, err := readPathOrContents(key)\n\t\tif err != nil {\n\t\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\t\tfmt.Errorf(\"Error loading encryption key: %s\", err),\n\t\t\t)\n\t\t}\n\n\t\t// The GCS client expects a customer supplied encryption key to be\n\t\t// passed in as a 32 byte long byte slice. The byte slice is base64\n\t\t// encoded before being passed to the API. We take a base64 encoded key\n\t\t// to remain consistent with the GCS docs.\n\t\t// https://cloud.google.com/storage/docs/encryption#customer-supplied\n\t\t// https://github.com/GoogleCloudPlatform/google-cloud-go/blob/def681/storage/storage.go#L1181\n\t\tk, err := base64.StdEncoding.DecodeString(kc)\n\t\tif err != nil {\n\t\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\t\tfmt.Errorf(\"Error decoding encryption key: %s\", err),\n\t\t\t)\n\t\t}\n\t\tb.encryptionKey = k\n\t}\n","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/gcs/backend.go#L250-L286","documentation":"The GCS backend allows customer-supplied encryption via 'encryption_key'. The value is passed through readPathOrContents, which treats it as a file path first and falls back to treating it as the literal content. If neither resolves (file does not exist / unreadable), this error is returned with the OS error in %s. It fires before any base64 decoding is attempted.","triggerScenarios":"encryption_key set to a path like '/run/secrets/gcs-key' that doesn't exist on the runner, or set via GOOGLE_ENCRYPTION_KEY to a path the process can't read, during 'terraform init' in Configure().","commonSituations":"Secret mounted to a different path in CI vs local; typo in the path; permission bits on the key file; encryption_key value intended as inline content but accidentally looks like a path.","solutions":["Verify the path exists and is readable by the terraform process: 'ls -l <path>' and 'test -r <path>'.","If the value is the key content itself (base64 string), confirm it doesn't contain '/' prefixes that make readPathOrContents treat it as a path.","Mount the secret at the configured path in CI (Vault/secret manager sidecar) or switch to passing the value via the GOOGLE_ENCRYPTION_KEY env var.","If you migrated to KMS, remove encryption_key and use kms_encryption_key instead."],"exampleFix":"// before\nencryption_key = \"/run/secrets/gcs-csek\"   # not mounted in CI\n\n// after\nencryption_key = file(\"${path.module}/keys/gcs-csek.b64\")\n# or via env\nexport GOOGLE_ENCRYPTION_KEY=$(cat keys/gcs-csek.b64)","handlingStrategy":"validation","validationCode":"// Verify the CSEK file is readable before invoking terraform\npath := \"/run/secrets/gcs-csek\"\nif _, err := os.ReadFile(path); err != nil {\n    log.Fatalf(\"encryption_key path unreadable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mount the secret at the configured path in every environment that runs terraform.","Use the GOOGLE_ENCRYPTION_KEY env var to avoid path coupling in CI.","Add a 'test -r <path>' step before 'terraform init' in pipelines."],"tags":["gcs","gcp","encryption","csek","secrets","config-validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}