juspay/hyperswitch · error · GcpKmsError
Failed to base64 decode input data
Error message
Failed to base64 decode input data
What it means
Thrown by GcpKmsClient::decrypt when the input data cannot be base64 decoded. The decrypt API expects ciphertext in base64 (matching the output of encrypt, which returns base64-encoded ciphertext). If the bytes passed are not valid base64 for the configured engine (standard padded base64), decoding fails and this error is returned. It occurs before any network call to GCP KMS is made.
Source
Thrown at crates/external_services/src/gcp_kms/core.rs:152
logger::error!(gcp_kms_error=?error, "Failed to GCP KMS encrypt data");
metrics::GCP_KMS_ENCRYPTION_FAILURES.add(1, &[]);
})
.change_context(GcpKmsError::EncryptionFailed)?;
let output = consts::BASE64_ENGINE.encode(response.ciphertext);
let time_taken = start.elapsed();
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,
}View on GitHub (pinned to 806ec7dcc0)
Solutions
- Verify the input is valid standard base64 before calling decrypt (decode it with base64::engine::general_purpose::STANDARD in a test)
- If the ciphertext came from another system, check whether it uses base64url (- and _ instead of + and /) and translate or use the appropriate engine
- Ensure the ciphertext was produced by GcpKmsClient::encrypt, which returns standard base64 with padding
- Inspect stored/transferred ciphertext for truncation, embedded newlines, or URL-encoding artifacts
Example fix
// before: passing raw binary or non-padded base64
let plaintext = client.decrypt(raw_ciphertext_bytes).await?;
// after: ensure input is standard padded base64, as produced by encrypt()
use base64::Engine;
let normalized = ciphertext_str.trim();
let validated = base64::engine::general_purpose::STANDARD
.decode(normalized)
.map_err(|e| format!("not valid base64: {e}"))?;
let plaintext = client.decode_pre_validated(validated).await?; // or just pass `normalized` Defensive patterns
Strategy: validation
Validate before calling
use base64::Engine;
fn is_valid_standard_b64(input: &str) -> bool {
base64::engine::general_purpose::STANDARD
.decode(input.trim())
.is_ok()
}
// before calling decrypt:
if !is_valid_standard_b64(&ciphertext) {
return Err("ciphertext is not valid base64");
}
let plaintext = client.decrypt(ciphertext.trim()).await?; Try / catch
match client.decrypt(data).await {
Ok(s) => s,
Err(e) if matches!(e.current_context(), GcpKmsError::Base64DecodingFailed) => {
// reject the stored ciphertext / alert on data corruption; do not retry
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Always use the String returned by encrypt() verbatim as the decrypt() input
- Store ciphertext in text-safe columns and avoid trimming padding characters
- Validate base64 at ingestion boundaries before persisting ciphertext
When it happens
Trigger: Calling GcpKmsClient::decrypt with a string/bytes that is not valid base64 (e.g. raw binary ciphertext, corrupted/modified base64, wrong padding or charset, or ciphertext produced by a different encoding scheme such as base64url without translation). Raised at the consts::BASE64_ENGINE.decode(data) call in crates/external_services/src/gcp_kms/core.rs:86-88.
Common situations: Passing raw binary ciphertext that was never base64 encoded; round-tripping data through a system that strips or re-encodes padding; using base64url-encoded tokens from JWTs or external APIs; double-decoding or truncation of the ciphertext in transit or storage; copy-pasting ciphertext with whitespace/newlines embedded.
Related errors
- Failed UTF-8 decode of GCP KMS decrypted output
- Failed to GCP KMS decrypt input data
- Failed to GCP KMS encrypt input data
- Failed to create GCP KMS client
AI-assisted analysis of juspay/hyperswitch@806ec7dcc0 (2026-08-28).
Data as JSON: /api/errors/09385f1f2b1f9569.
Report an issue: GitHub.