gchq/CyberChef · error · OperationError

Error: Invalid Base64 input length (${data.length}). Cannot

Error message

Error: Invalid Base64 input length (${data.length}). Cannot be 4n+1, even without padding chars.

What it means

Thrown by fromBase64() in src/core/lib/Base64.mjs:107 when strictMode is enabled and the (post character-removal) input string has a length congruent to 1 modulo 4. Base64 packs 3 bytes into 4 characters, so a remainder of 1 is mathematically impossible for any validly-produced Base64 string, even with padding stripped. The check exists to reject truncated or corrupted input early instead of silently emitting wrong bytes.

Source

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

    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) {
                // Check that the padding character is only used at the end and maximum of twice
                if (padPos < data.length - 2 || data.charAt(data.length - 1) !== pad) {
                    throw new OperationError(`Error: Base64 padding character (${pad}) not used in the correct place.`);
                }

                // Check that input is padded to the correct length
                if (data.length % 4 !== 0) {
                    throw new OperationError("Error: Base64 not padded to a multiple of 4.");
                }
            }
        }
    }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Re-acquire the source Base64 string and verify its length is a multiple of 4 (or 4n+2 / 4n+3 when unpadded).
  2. If you intentionally work with unpadded Base64, disable strictMode (pass false or omit the 5th argument).
  3. Pad the string to a multiple of 4 with '=' characters before decoding when the alphabet includes padding.
  4. Confirm removeNonAlphChars=true so stray whitespace/newlines are stripped before the length check.

Example fix

// before - throws when a char was dropped
fromBase64(truncatedStr, 'A-Za-z0-9+/=', 'byteArray', true, true);

// after - tolerate unpadded/non-strict input
fromBase64(truncatedStr, 'A-Za-z0-9+/=', 'byteArray', true, false);
Defensive patterns

Strategy: validation

Validate before calling

function isValidBase64Length(data, removeNonAlphChars, alphabet) {
  if (removeNonAlphChars) {
    const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
    data = data.replace(re, "");
  }
  return data.length % 4 !== 1;
}
// call: if (!isValidBase64Length(data, true, expandedAlphabet)) return null;

Type guard

function isPlausibleBase64(s) {
  return typeof s === 'string' && s.length > 0 && s.replace(/[^A-Za-z0-9+/=]/g, '').length % 4 !== 1;
}

Try / catch

try {
  const bytes = fromBase64(input, alphabet, 'byteArray', true, true);
} catch (e) {
  if (e instanceof OperationError && /Invalid Base64 input length/.test(e.message)) {
    // handle truncated/unpadded input
  }
}

Prevention

When it happens

Trigger: Calling fromBase64(data, alphabet, returnType, removeNonAlphChars, strictMode) with strictMode=true (5th arg) where, after non-alphabet chars are optionally stripped, data.length % 4 === 1. Example: fromBase64('SGVsbG8', 'A-Za-z0-9+/=', 'byteArray', true, true) after stripping yields length 7 (7%4===1). Also fires on lengths like 5, 9, 13, etc.

Common situations: Pasted Base64 that lost a character in transit (copy-paste truncation); concatenating Base64 fragments that split mid-quartet; stripping '=' padding AND a data char by accident; URL-safe variants where '-'/'_' got mangled before decoding; feeding hex or raw text that happens to be 4n+1 long while strictMode is on.

Related errors


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