{"record":{"id":"bbc0721868b28b20","repo":"juspay/hyperswitch","slug":"failed-to-gcp-kms-encrypt-input-data","errorCode":null,"errorMessage":"Failed to GCP KMS encrypt input data","messagePattern":"Failed to GCP KMS encrypt input data","errorType":"exception","errorClass":"GcpKmsError","httpStatus":null,"severity":"critical","filePath":"crates/external_services/src/gcp_kms/core.rs","lineNumber":160,"sourceCode":"        metrics::GCP_KMS_ENCRYPT_TIME.record(time_taken.as_secs_f64(), &[]);\n\n        Ok(output)\n    }\n}\n\n/// Errors that could occur during GCP KMS operations.\n#[derive(Debug, thiserror::Error)]\npub 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 {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/juspay/hyperswitch/blob/806ec7dcc036d895b93313d5e8eaa2374e25bcdf/crates/external_services/src/gcp_kms/core.rs#L142-L178","documentation":"Thrown when the underlying google_cloud_kms client's encrypt RPC fails inside GcpKmsClient::encrypt. The plaintext was accepted locally; this error means GCP Cloud KMS rejected or failed the EncryptRequest. The original gRPC error is logged (gcp_kms_error) and the GCP_KMS_ENCRYPTION_FAILURES metric incremented before this context is applied.","triggerScenarios":"Calling GcpKmsClient::encrypt and inner_client.encrypt(request, None) returning an error at crates/external_services/src/gcp_kms/core.rs:129-137. Causes include: malformed key name built from GcpKmsConfig (wrong project_id/location_id/key_ring_id/key_id), missing roles/cloudkms.cryptoKeyEncrypter IAM role, key disabled/pending deletion, plaintext exceeding the KMS size limit (~64 KiB for symmetric keys), or connectivity failure to cloudkms.googleapis.com.","commonSituations":"Config typos in the key resource path; service account without encrypter role; KMS key left disabled after an incident drill; encrypting large payloads (whole files) instead of DEK-wrapping patterns; ADC missing in local dev/CI; intermittent network issues between the service and GCP.","solutions":["Check the 'Failed to GCP KMS encrypt data' log with gcp_kms_error — the gRPC status code identifies the issue","Verify the config builds the correct resource name: projects/LOCATION/... cross-check with gcloud kms keys list","Grant roles/cloudkms.cryptoKeyEncrypter (or EncrypterDecrypter) to the authenticated principal","Keep plaintext under the KMS limit (~64 KiB); envelope-encrypt larger data with a locally generated DEK","Confirm the key is enabled and not scheduled for destruction"],"exampleFix":"// before: encrypting arbitrarily large payloads directly\nlet ct = client.encrypt(file_bytes).await?; // may exceed 64 KiB limit\n\n// after: envelope encryption — encrypt only a data key\nlet dek = generate_random_32_bytes();\nlet wrapped_dek = client.encrypt(&dek).await?;\nlet file_ct = aes_gcm_encrypt(&dek, file_bytes);","handlingStrategy":"retry","validationCode":"// Pre-checks before encrypt:\nif let Err(msg) = gcp_kms_config.validate() {\n    return Err(msg);\n}\nconst KMS_MAX_PLAINTEXT: usize = 64 * 1024; // ~64 KiB limit for symmetric keys\nif data.as_ref().len() > KMS_MAX_PLAINTEXT {\n    return Err(\"payload too large for direct KMS encryption; use envelope encryption\");\n}","typeGuard":null,"tryCatchPattern":"match client.encrypt(data).await {\n    Ok(ct) => ct,\n    Err(e) if matches!(e.current_context(), GcpKmsError::EncryptionFailed) => {\n        // inspect logged gcp_kms_error; retry only transient gRPC statuses\n        // (Unavailable/DeadlineExceeded) with backoff; surface config/IAM issues\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Health-check the KMS client at startup with a small encrypt/decrypt round-trip","Envelope-encrypt anything larger than a small secret; never send whole files to KMS","Ensure the encrypter IAM role is granted via IaC so environments stay in sync","Alert on the GCP_KMS_ENCRYPTION_FAILURES metric"],"tags":["gcp-kms","grpc","rust","iam","encryption","cloud"],"backgroundTag":"cloud-kms-encrypt-failed","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"}