gchq/CyberChef · error · OperationError
Error: Base64 input contains non-alphabet char(s)
Error message
Error: Base64 input contains non-alphabet char(s)
What it means
Thrown by fromBase64() in src/core/lib/Base64.mjs:140 during the decode loop, under strictMode, when alphabet.indexOf() returns -1 for any of the four quartet characters — meaning a byte survived into the loop that is not in the alphabet (including the pad slot). Because the earlier removeNonAlphChars pass strips everything outside the alphabet+pad, this error in practice requires removeNonAlphChars=false so that foreign characters reach the decoder.
Source
Thrown at src/core/lib/Base64.mjs:140
}
}
}
}
const output = [];
let chr1, chr2, chr3,
enc1, enc2, enc3, enc4,
i = 0;
while (i < data.length) {
// Including `|| null` forces empty strings to null so that indexOf returns -1 instead of 0
enc1 = alphabet.indexOf(data.charAt(i++) || null);
enc2 = alphabet.indexOf(data.charAt(i++) || null);
enc3 = alphabet.indexOf(data.charAt(i++) || null);
enc4 = alphabet.indexOf(data.charAt(i++) || null);
if (strictMode && (enc1 < 0 || enc2 < 0 || enc3 < 0 || enc4 < 0)) {
throw new OperationError("Error: Base64 input contains non-alphabet char(s)");
}
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
if (chr1 >= 0 && chr1 < 256) {
output.push(chr1);
}
if (chr2 >= 0 && chr2 < 256 && enc3 !== 64) {
output.push(chr2);
}
if (chr3 >= 0 && chr3 < 256 && enc4 !== 64) {
output.push(chr3);
}
}
return returnType === "string" ? Utils.byteArrayToUtf8(output) : output;View on GitHub (pinned to 4290ea7539)
Solutions
- Pass removeNonAlphChars=true (the default) so out-of-alphabet characters are stripped before decoding.
- Pre-trim the input: data.replace(/[^A-Za-z0-9+/=]/g, '') for the standard alphabet.
- Verify the alphabet option matches how the string was produced (Standard vs URL-safe vs itoa64).
- If you genuinely need strict rejection, keep strictMode=true but clean the input first.
Example fix
// before - space not in alphabet, removal disabled
fromBase64('AB CD', 'A-Za-z0-9+/=', 'byteArray', false, true);
// after - let the library strip non-alphabet chars
fromBase64('AB CD', 'A-Za-z0-9+/=', 'byteArray', true, true); Defensive patterns
Strategy: validation
Validate before calling
function containsOnlyAlphabet(data, alphabet) {
for (const ch of data) {
if (alphabet.indexOf(ch) < 0) return false;
}
return true;
}
// or simply pass removeNonAlphChars=true to fromBase64 Type guard
function isPureStandardBase64(s) {
return typeof s === 'string' && /^[A-Za-z0-9+/=]*$/.test(s);
} Try / catch
try {
fromBase64(input, 'A-Za-z0-9+/=', 'byteArray', false, true);
} catch (e) {
if (e instanceof OperationError && /non-alphabet char/.test(e.message)) {
input = input.replace(/[^A-Za-z0-9+/=]/g, '');
}
} Prevention
- Keep removeNonAlphChars at its default true unless you have a specific reason.
- If you disable removal, pre-sanitize the input to the chosen alphabet.
- Match the alphabet option to how the data was encoded.
When it happens
Trigger: fromBase64(data, alphabet, returnType, removeNonAlphChars=false, strictMode=true) where data contains any char not in the expanded alphabet. Example: fromBase64('AB CD', 'A-Za-z0-9+/=', 'byteArray', false, true) — the space is not in the alphabet, indexOf returns -1, throws.
Common situations: Whitespace or newlines in pasted Base64 when the caller explicitly disabled character removal; mixing alphabets (e.g. url-safe '-/_' fed to the standard alphabet); embedded null bytes or BOM; binary data mistakenly treated as a Base64 string.
Related errors
- Error: Invalid Base64 input length (${data.length}). Cannot
- Error: Base64 padding character (${pad}) not used in the cor
- Error: Base64 not padded to a multiple of 4.
- Error: Base64 alphabet should be 64 characters long, or 65 w
- ${val} is not a base92 character
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/55df5a17e2816dec.
Report an issue: GitHub.