{"record":{"id":"09385f1f2b1f9569","repo":"juspay/hyperswitch","slug":"failed-to-base64-decode-input-data","errorCode":null,"errorMessage":"Failed to base64 decode input data","messagePattern":"Failed to base64 decode input data","errorType":"exception","errorClass":"GcpKmsError","httpStatus":null,"severity":"error","filePath":"crates/external_services/src/gcp_kms/core.rs","lineNumber":152,"sourceCode":"                logger::error!(gcp_kms_error=?error, \"Failed to GCP KMS encrypt data\");\n                metrics::GCP_KMS_ENCRYPTION_FAILURES.add(1, &[]);\n            })\n            .change_context(GcpKmsError::EncryptionFailed)?;\n\n        let output = consts::BASE64_ENGINE.encode(response.ciphertext);\n\n        let time_taken = start.elapsed();\n        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}","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/juspay/hyperswitch/blob/806ec7dcc036d895b93313d5e8eaa2374e25bcdf/crates/external_services/src/gcp_kms/core.rs#L134-L170","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: passing raw binary or non-padded base64\nlet plaintext = client.decrypt(raw_ciphertext_bytes).await?;\n\n// after: ensure input is standard padded base64, as produced by encrypt()\nuse base64::Engine;\nlet normalized = ciphertext_str.trim();\nlet validated = base64::engine::general_purpose::STANDARD\n    .decode(normalized)\n    .map_err(|e| format!(\"not valid base64: {e}\"))?;\nlet plaintext = client.decode_pre_validated(validated).await?; // or just pass `normalized`","handlingStrategy":"validation","validationCode":"use base64::Engine;\n\nfn is_valid_standard_b64(input: &str) -> bool {\n    base64::engine::general_purpose::STANDARD\n        .decode(input.trim())\n        .is_ok()\n}\n\n// before calling decrypt:\nif !is_valid_standard_b64(&ciphertext) {\n    return Err(\"ciphertext is not valid base64\");\n}\nlet plaintext = client.decrypt(ciphertext.trim()).await?;","typeGuard":null,"tryCatchPattern":"match client.decrypt(data).await {\n    Ok(s) => s,\n    Err(e) if matches!(e.current_context(), GcpKmsError::Base64DecodingFailed) => {\n        // reject the stored ciphertext / alert on data corruption; do not retry\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["gcp-kms","base64","rust","decoding","validation"],"backgroundTag":"invalid-base64-input","analyzedSha":"806ec7dcc036d895b93313d5e8eaa2374e25bcdf","analyzedAt":"2026-08-28T16:43:48.683Z","contentChangedAt":"2026-08-28T16:43:48.683Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}