juspay/hyperswitch · critical · GcpKmsError
Failed to GCP KMS encrypt input data
Error message
Failed to GCP KMS encrypt input data
What it means
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.
Source
Thrown at crates/external_services/src/gcp_kms/core.rs:160
metrics::GCP_KMS_ENCRYPT_TIME.record(time_taken.as_secs_f64(), &[]);
Ok(output)
}
}
/// Errors that could occur during GCP KMS operations.
#[derive(Debug, thiserror::Error)]
pub enum GcpKmsError {
/// An error occurred when base64 decoding the input data.
#[error("Failed to base64 decode input data")]
Base64DecodingFailed,
/// An error occurred when GCP KMS decrypting the input data.
#[error("Failed to GCP KMS decrypt input data")]
DecryptionFailed,
/// An error occurred when GCP KMS encrypting the input data.
#[error("Failed to GCP KMS encrypt input data")]
EncryptionFailed,
/// An error occurred UTF-8 decoding the GCP KMS decrypted output.
#[error("Failed UTF-8 decode of GCP KMS decrypted output")]
Utf8DecodingFailed,
/// An error occurred when creating the GCP KMS client.
#[error("Failed to create GCP KMS client")]
ClientCreationFailed,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn validate_fails_when_project_id_is_empty() {
let config = GcpKmsConfig {View on GitHub (pinned to 806ec7dcc0)
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
Example fix
// before: encrypting arbitrarily large payloads directly let ct = client.encrypt(file_bytes).await?; // may exceed 64 KiB limit // after: envelope encryption — encrypt only a data key let dek = generate_random_32_bytes(); let wrapped_dek = client.encrypt(&dek).await?; let file_ct = aes_gcm_encrypt(&dek, file_bytes);
Defensive patterns
Strategy: retry
Validate before calling
// Pre-checks before encrypt:
if let Err(msg) = gcp_kms_config.validate() {
return Err(msg);
}
const KMS_MAX_PLAINTEXT: usize = 64 * 1024; // ~64 KiB limit for symmetric keys
if data.as_ref().len() > KMS_MAX_PLAINTEXT {
return Err("payload too large for direct KMS encryption; use envelope encryption");
} Try / catch
match client.encrypt(data).await {
Ok(ct) => ct,
Err(e) if matches!(e.current_context(), GcpKmsError::EncryptionFailed) => {
// inspect logged gcp_kms_error; retry only transient gRPC statuses
// (Unavailable/DeadlineExceeded) with backoff; surface config/IAM issues
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to GCP KMS decrypt input data
- Failed to create GCP KMS client
- Failed to base64 decode input data
- Failed UTF-8 decode of GCP KMS decrypted output
AI-assisted analysis of juspay/hyperswitch@806ec7dcc0 (2026-08-28).
Data as JSON: /api/errors/bbc0721868b28b20.
Report an issue: GitHub.