{"record":{"id":"c3e19f83ba90db82","repo":"hashicorp/terraform","slug":"error-decoding-encryption-key-s","errorCode":null,"errorMessage":"Error decoding encryption key: %s","messagePattern":"Error decoding encryption key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/backend.go","lineNumber":281,"sourceCode":"\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\n\t// Customer-managed encryption\n\tkmsName := data.String(\"kms_encryption_key\")\n\tif kmsName != \"\" {\n\t\tb.kmsKeyName = kmsName\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":263,"sourceCodeEnd":295,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/gcs/backend.go#L263-L295","documentation":"Thrown when the bytes read from encryption_key are not valid standard base64. The GCS backend expects a 32-byte key supplied base64-encoded (consistent with the GCS customer-supplied encryption docs), so after reading it decodes with base64.StdEncoding.","triggerScenarios":"readPathOrContents returns content, but base64.StdEncoding.DecodeString returns an error — e.g., the key is raw bytes, hex-encoded, URL-safe base64, contains whitespace/newlines that StdEncoding rejects, or has wrong padding.","commonSituations":"User generated a key with `openssl rand 32` and pasted raw bytes; used `base64.URLStringEncoding`; the file has a trailing newline that breaks strict StdEncoding; key was generated by a tool emitting hex.","solutions":["Regenerate the key as base64 of 32 random bytes: `openssl rand -base64 32`.","Strip trailing whitespace/newlines from the key content before supplying it.","Ensure you are using standard (not URL-safe) base64 with correct '=' padding.","Confirm the decoded length is exactly 32 bytes."],"exampleFix":"// before — raw bytes or wrong encoding\nexport TF_ENC_KEY=$(openssl rand 32 | base64)  # newline included\n// after\nexport TF_ENC_KEY=$(openssl rand -base64 32 | tr -d '\\n')","handlingStrategy":"validation","validationCode":"decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(kc))\nif err != nil {\n    return fmt.Errorf(\"encryption_key must be base64(32 bytes); regenerate with `openssl rand -base64 32`\")\n}\nif len(decoded) != 32 {\n    return fmt.Errorf(\"encryption_key decodes to %d bytes, expected 32\", len(decoded))\n}","typeGuard":"func isValidGCSEncryptionKey(s string) bool {\n    b, err := base64.StdEncoding.DecodeString(strings.TrimSpace(s))\n    return err == nil && len(b) == 32\n}","tryCatchPattern":null,"preventionTips":["Generate keys only with `openssl rand -base64 32` and trim newlines.","Add a CI lint that validates the supplied key length after base64 decode."],"tags":["gcs","backend","encryption","base64","configuration"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}