{"record":{"id":"4e276c1c4cd2a5b1","repo":"hashicorp/terraform","slug":"can-t-set-both-encryption-key-and-kms-encryption-k","errorCode":null,"errorMessage":"can't set both encryption_key and kms_encryption_key","messagePattern":"can't set both encryption_key and kms_encryption_key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/backend.go","lineNumber":148,"sourceCode":"\t\t\t},\n\t\t},\n\t}\n}\n\nfunc (b *Backend) Configure(configVal cty.Value) tfdiags.Diagnostics {\n\tif b.storageClient != nil {\n\t\treturn nil\n\t}\n\n\t// TODO: Update the Backend API to pass the real context.Context from\n\t// the running command.\n\tctx := context.TODO()\n\n\tdata := backendbase.NewSDKLikeData(configVal)\n\n\tif data.String(\"encryption_key\") != \"\" && data.String(\"kms_encryption_key\") != \"\" {\n\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\tfmt.Errorf(\"can't set both encryption_key and kms_encryption_key\"),\n\t\t)\n\t}\n\t// The above catches the main case where both of the arguments are set to\n\t// a non-empty value, but we also want to reject the situation where\n\t// both are present in the configuration regardless of what values were\n\t// assigned to them. (This check doesn't take the environment variables\n\t// into account, so must allow neither to be set in the main configuration.)\n\tif !(configVal.GetAttr(\"encryption_key\").IsNull() || configVal.GetAttr(\"kms_encryption_key\").IsNull()) {\n\t\t// This rejects a configuration like:\n\t\t//     encryption_key     = \"\"\n\t\t//     kms_encryption_key = \"\"\n\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\tfmt.Errorf(\"can't set both encryption_key and kms_encryption_key\"),\n\t\t)\n\t}\n\n\tb.bucketName = data.String(\"bucket\")\n\tb.prefix = strings.TrimLeft(data.String(\"prefix\"), \"/\")","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/gcs/backend.go#L130-L166","documentation":"Raised by the GCS backend's Configure() when both 'encryption_key' and 'kms_encryption_key' resolve to non-empty values. GCS state can be encrypted with either a customer-supplied key (CSEK) or a customer-managed KMS key (CMEK), but not both at once — specifying both is ambiguous and rejected. This is the value-based check (the second check at line 156 handles the both-present-but-empty case).","triggerScenarios":"At backend.go:146-149: data.String(\"encryption_key\") != \"\" && data.String(\"kms_encryption_key\") != \"\". Triggered on 'terraform init' when the backend block (or GOOGLE_ENCRYPTION_KEY + GOOGLE_KMS_ENCRYPTION_KEY env vars) supplies both keys.","commonSituations":"Configuring both encryption methods intentionally by mistake; GOOGLE_ENCRYPTION_KEY left exported in the shell while also setting kms_encryption_key in the backend block; copy-pasting a backend block from docs and forgetting to delete one.","solutions":["Choose exactly one encryption method: keep either encryption_key (CSEK) or kms_encryption_key (CMEK), and remove the other.","If using env vars, unset the one you do not want (e.g. 'unset GOOGLE_ENCRYPTION_KEY').","Re-run 'terraform init' after editing the backend block."],"exampleFix":"# before: both set\nterraform {\n  backend \"gcs\" {\n    bucket            = \"tf-state\"\n    encryption_key    = \"Qk...==\"\n    kms_encryption_key = \"projects/p/locations/global/keyRings/r/cryptoKeys/k\"\n  }\n}\n# after: keep only one (CMEK here)\nterraform {\n  backend \"gcs\" {\n    bucket             = \"tf-state\"\n    kms_encryption_key = \"projects/p/locations/global/keyRings/r/cryptoKeys/k\"\n  }\n}","handlingStrategy":"validation","validationCode":"// Validate the backend config before init.\nfunc validateGCSBackend(encKey, kmsKey string) error {\n    if encKey != \"\" && kmsKey != \"\" {\n        return fmt.Errorf(\"can't set both encryption_key and kms_encryption_key\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set exactly one of encryption_key / kms_encryption_key (or neither).","Unset GOOGLE_ENCRYPTION_KEY / GOOGLE_KMS_ENCRYPTION_KEY when not in use.","Lint the backend block in CI to catch dual-set configs."],"tags":["gcs","google-cloud","encryption","config","validation","kms","csek"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}