gchq/CyberChef · error · OperationError

Error: Base64 alphabet should be 64 characters long, or 65 w

Error message

Error: Base64 alphabet should be 64 characters long, or 65 with a padding character. Found ${alphabet.length}: ${alphabet}

What it means

Thrown by fromBase64() (Base64.mjs line 95) after expanding the alphabet, when its length is not 64 (or 65 with padding). Distinct from toBase64: fromBase64 first does alphabet = alphabet || 'A-Za-z0-9+/=' (line 90), so an empty/null/falsy alphabet is replaced by the default and does NOT throw - only a non-empty, wrong-length alphabet triggers this.

Source

Thrown at src/core/lib/Base64.mjs:95

 *
 * @example
 * // returns "Hello"
 * fromBase64("SGVsbG8=");
 *
 * // returns [72, 101, 108, 108, 111]
 * fromBase64("SGVsbG8=", null, "byteArray");
 */
export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", removeNonAlphChars=true, strictMode=false) {
    if (!data) {
        return returnType === "string" ? "" : [];
    }

    alphabet = alphabet || "A-Za-z0-9+/=";
    alphabet = Utils.expandAlphRange(alphabet).join("");

    // Confirm alphabet is a valid length
    if (alphabet.length !== 64 && alphabet.length !== 65) { // Allow for padding
        throw new OperationError(`Error: Base64 alphabet should be 64 characters long, or 65 with a padding character. Found ${alphabet.length}: ${alphabet}`);
    }

    // Remove non-alphabet characters
    if (removeNonAlphChars) {
        const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
        data = data.replace(re, "");
    }

    if (strictMode) {
        // Check for incorrect lengths (even without padding)
        if (data.length % 4 === 1) {
            throw new OperationError(`Error: Invalid Base64 input length (${data.length}). Cannot be 4n+1, even without padding chars.`);
        }

        if (alphabet.length === 65) { // Padding character included
            const pad = alphabet.charAt(64);
            const padPos = data.indexOf(pad);
            if (padPos >= 0) {

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Pass null/undefined/'' to use the standard default alphabet.
  2. Supply exactly 64 chars (no padding) or 65 chars (with padding as the 65th).
  3. For URL-safe Base64 use 'A-Za-z0-9-_' (64, no padding) or add '=' for 65.
  4. Use the matching operation for other bases.

Example fix

// before
fromBase64(data, 'A-Z0-9'); // 36 chars

// after
fromBase64(data); // default
fromBase64(data, 'A-Za-z0-9-_'); // URL-safe, 64 chars
Defensive patterns

Strategy: validation

Validate before calling

import Utils from './core/Utils.mjs';
function validFromB64Alphabet(a) {
  if (!a) return true; // empty/null uses default
  const len = Utils.expandAlphRange(a).join('').length;
  return len === 64 || len === 65;
}

Type guard

function isFromBase64Alphabet(a): boolean { if (!a) return true; const n = Utils.expandAlphRange(a).join('').length; return n === 64 || n === 65; }

Try / catch

try { fromBase64(data, alphabet); } catch (e) {
  if (e instanceof OperationError && /Base64 alphabet should be 64 characters/.test(e.message)) { alphabet = null; }
}

Prevention

When it happens

Trigger: Calling fromBase64(data, 'A-Z0-9') (36 chars); passing a URL-safe or custom alphabet that has the wrong count (e.g. 'A-Za-z0-9-_' without padding = 64 is fine, but a typo dropping a char gives 63); using a Base32/58 alphabet for Base64 decoding.

Common situations: User supplies a malformed custom alphabet in the 'From Base64' operation; URL-safe alphabet missing the padding char or one symbol; recipe carrying a custom alphabet that was edited/truncated.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/23111d37d2a6f11b. Report an issue: GitHub.