stalwartlabs/stalwart · error
Failed to decode base64
Error message
Failed to decode base64
What it means
`base64_decode` in the console module wraps `base64::general_purpose::STANDARD.decode(input)` in `.expect("Failed to decode base64")`, so any invalid base64 input panics. It is used by `parse_key`/`parse_value` when console input is prefixed with `base64:`, and by PEM/blob/pkey parsing helpers (simple_pem_parse, get_blob_section, parse_public_key, verify_secret_hash). Standard-alphabet decoding with strict padding is enforced; URL-safe characters or missing/incorrect padding cause the panic.
Source
Thrown at crates/common/src/manager/console.rs:247
Some(result)
} else {
println!("Invalid key: {result:?}");
None
}
}
fn parse_value(input: &str) -> Vec<u8> {
if let Some(key) = input.strip_prefix("base64:") {
base64_decode(key)
} else {
parse_binary(input)
}
}
fn base64_decode(input: &str) -> Vec<u8> {
general_purpose::STANDARD
.decode(input)
.expect("Failed to decode base64")
}
fn parse_binary(input: &str) -> Vec<u8> {
let mut result = Vec::new();
let mut chars = input.chars().peekable();
while let Some(c) = chars.next() {
if c == '\\' {
match chars.next() {
Some('x') => {
let hex: String = chars.by_ref().take(2).collect();
if hex.len() == 2 {
if let Ok(byte) = u8::from_str_radix(&hex, 16) {
result.push(byte);
} else {
result.extend_from_slice(b"\\x");
result.extend_from_slice(hex.as_bytes());
}View on GitHub (pinned to e962003857)
Solutions
- Validate the base64 string before use: only A-Z a-z 0-9 + / with proper = padding (or re-pad it), e.g. decode it first with `base64 -d` or a quick script.
- Re-encode the data in standard (padded) base64: `echo -n "<raw>" | base64` and use that output after the `base64:` prefix.
- Convert URL-safe base64 to standard: replace `-` with `+`, `_` with `/`, and append the required `=` padding before decoding.
- Strip all whitespace/newlines from the payload before passing it, and use the `\xNN` escaped-hex input format as a fallback when base64 keeps failing.
Example fix
// before scan base64:cmFjYXNk base64:cmFjYXNkZg // missing padding -> panic // after scan base64:cmFjYXNk base64:cmFjYXNkZg== // correct standard padding
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_standard_base64(s: &str) -> bool {
let trimmed: String = s.chars().filter(|c| !c.is_whitespace()).collect();
base64::engine::general_purpose::STANDARD.decode(&trimmed).is_ok()
}
// call before passing `base64:<payload>` to console commands Type guard
fn safe_base64_decode(input: &str) -> Option<Vec<u8>> {
base64::engine::general_purpose::STANDARD.decode(input).ok()
} Try / catch
// replace .expect with fallible handling
fn base64_decode(input: &str) -> Result<Vec<u8>, base64::DecodeError> {
base64::engine::general_purpose::STANDARD.decode(input)
} Prevention
- Only paste standard, padded base64 after the `base64:` prefix — no URL-safe `-`/`_` alphabets.
- Re-encode with `base64` CLI or your language's standard encoder before using console arguments.
- Strip all whitespace/newlines from copied payloads.
- Never truncate base64 strings manually; truncation breaks length/padding.
- Prefer the `\xNN` escaped-hex input format when base64 validation keeps failing.
When it happens
Trigger: Typing `scan/get/put/delete` console arguments like `base64:abc!` or `base64:cmV` (invalid character, wrong length, or missing padding); passing a PEM blob, public key, or secret hash string containing URL-safe base64 (`-`/`_`), whitespace inside the payload, or truncated data into the parsing helpers.
Common situations: Pasting base64 from tools that produce URL-safe base64 (JWT segments, some JSON serializers) into the console; copying base64 with line breaks that were stripped incorrectly leaving stray characters; hand-truncating a key and losing `=` padding; base64 of a value copied from a doc with typographic characters.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to scan keys
- Failed to delete keys
- unwrap_tls called on non-TLS acceptor
- Migration aborted: {message}
- Failed to parse calendar template
AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06).
Data as JSON: /api/errors/a093182d0d986c12.
Report an issue: GitHub.