{"record":{"id":"4b3886150972dd93","repo":"juspay/hyperswitch","slug":"failed-to-create-gcp-kms-client","errorCode":null,"errorMessage":"Failed to create GCP KMS client","messagePattern":"Failed to create GCP KMS client","errorType":"exception","errorClass":"GcpKmsError","httpStatus":null,"severity":"critical","filePath":"crates/external_services/src/gcp_kms/core.rs","lineNumber":168,"sourceCode":"pub enum GcpKmsError {\n    /// An error occurred when base64 decoding the input data.\n    #[error(\"Failed to base64 decode input data\")]\n    Base64DecodingFailed,\n\n    /// An error occurred when GCP KMS decrypting the input data.\n    #[error(\"Failed to GCP KMS decrypt input data\")]\n    DecryptionFailed,\n\n    /// An error occurred when GCP KMS encrypting the input data.\n    #[error(\"Failed to GCP KMS encrypt input data\")]\n    EncryptionFailed,\n\n    /// An error occurred UTF-8 decoding the GCP KMS decrypted output.\n    #[error(\"Failed UTF-8 decode of GCP KMS decrypted output\")]\n    Utf8DecodingFailed,\n\n    /// An error occurred when creating the GCP KMS client.\n    #[error(\"Failed to create GCP KMS client\")]\n    ClientCreationFailed,\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn validate_fails_when_project_id_is_empty() {\n        let config = GcpKmsConfig {\n            project_id: String::new(),\n            location_id: \"global\".to_string(),\n            key_ring_id: \"key-ring\".to_string(),\n            key_id: \"key\".to_string(),\n        };\n        assert!(config.validate().is_err());\n    }\n","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/juspay/hyperswitch/blob/806ec7dcc036d895b93313d5e8eaa2374e25bcdf/crates/external_services/src/gcp_kms/core.rs#L150-L186","documentation":"Thrown by GcpKmsClient::new when either ClientConfig::default().with_auth() fails to obtain ambient GCP credentials, or Client::new fails to construct the KMS client (channel/gRPC setup). This is a startup/config-time error: no credentials, unreachable metadata server, or invalid ADC configuration. The underlying error is converted via change_context.","triggerScenarios":"Calling GcpKmsClient::new(&config) where with_auth() cannot resolve Application Default Credentials (no GOOGLE_APPLICATION_CREDENTIALS, no gcloud ADC, not on GCE/GKE with metadata server), or Client::new fails (cannot establish gRPC channel to cloudkms.googleapis.com). See crates/external_services/src/gcp_kms/core.rs:66-73.","commonSituations":"Local development without running gcloud auth application-default login; missing GOOGLE_APPLICATION_CREDENTIALS env var in containers/CI; service account JSON expired or malformed; workload identity not configured on GKE; egress proxy/firewall blocking metadata server or cloudkms.googleapis.com; readonly filesystem preventing ADC cache.","solutions":["Run gcloud auth application-default login locally, or set GOOGLE_APPLICATION_CREDENTIALS to the service account JSON path","Verify credentials resolve: gcloud auth application-default print-access-token","On GKE, check Workload Identity binding for the pod's service account; on GCE, confirm the metadata server is reachable (169.254.169.254)","Inspect the error_chain/attached source via error_stack Display to see the exact auth failure (expired token, file not found, channel error)","Ensure network egress to cloudkms.googleapis.com:443 is allowed"],"exampleFix":"# before: container starts with no ADC\nRUN echo \"no creds baked\"\nENV GOOGLE_APPLICATION_CREDENTIALS=\n\n# after: mount SA credentials and point ADC at them\ndocker run -v $PWD/sa.json:/secrets/sa.json \\\n  -e GOOGLE_APPLICATION_CREDENTIALS=/secrets/sa.json \\\n  my-service","handlingStrategy":"try-catch","validationCode":"// Fail fast at boot before any business logic:\nif let Err(msg) = gcp_kms_config.validate() {\n    return Err(format!(\"invalid GCP KMS config: {msg}\"));\n}\n// Optionally probe ADC availability first (cheap local check):\n#[cfg(feature = \"gcp\")] {\n    if std::env::var(\"GOOGLE_APPLICATION_CREDENTIALS\").is_err()\n        && !gcloud_adc_exists()\n        && !running_on_gcp_metadata()\n    {\n        return Err(\"no Application Default Credentials found for GCP KMS\");\n    }\n}\nlet kms = GcpKmsClient::new(&gcp_kms_config).await?;","typeGuard":null,"tryCatchPattern":"match GcpKmsClient::new(&config).await {\n    Ok(client) => client,\n    Err(e) if matches!(e.current_context(), GcpKmsError::ClientCreationFailed) => {\n        // startup-fatal: print the full error_stack chain (auth vs channel)\n        // and abort with a clear config error rather than retrying blindly\n        let mut msg = String::from(\"GCP KMS client creation failed:\");\n        for frame in e.chain() {\n            msg.push_str(&format!(\"\\n  caused by: {frame}\"));\n        }\n        anyhow::bail!(msg);\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Run gcloud auth application-default login in dev; set GOOGLE_APPLICATION_CREDENTIALS in CI/containers","Validate GcpKmsConfig at startup and include KMS config in integration smoke tests","Use Workload Identity on GKE instead of mounting key files where possible","Fail fast at boot: construct the KMS client during initialization, not lazily mid-request"],"tags":["gcp-kms","authentication","rust","startup","cloud","credentials"],"backgroundTag":"google-application-default-credentials-missing","analyzedSha":"806ec7dcc036d895b93313d5e8eaa2374e25bcdf","analyzedAt":"2026-08-28T16:43:48.683Z","contentChangedAt":"2026-08-28T16:43:48.683Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}