gchq/CyberChef · error · OperationError

Character not in alphabet: '${c}'

Error message

Character not in alphabet: '${c}'

What it means

Thrown by From Base45 when a character in the (possibly filtered) input is not found in the 45-character alphabet (alphabet.indexOf(c) === -1). This only fires when 'Remove non-alphabet chars' is disabled, because otherwise such characters are stripped first. The offending character is shown in the message.

Source

Thrown at src/core/operations/FromBase45.mjs:71

        if (!input) return [];
        const alphabet = Utils.expandAlphRange(args[0]).join("");
        const removeNonAlphChars = args[1];

        const res = [];

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

        for (const triple of Utils.chunked(input, 3)) {
            triple.reverse();
            let b = 0;
            for (const c of triple) {
                const idx = alphabet.indexOf(c);
                if (idx === -1) {
                    throw new OperationError(`Character not in alphabet: '${c}'`);
                }
                b *= 45;
                b += idx;
            }

            if (b > 65535) {
                throw new OperationError(`Triplet too large: '${triple.join("")}'`);
            }

            if (triple.length > 2) {
                /**
                 * The last triple may only have 2 bytes so we push the MSB when we got 3 bytes
                 * Pushing MSB
                 */
                res.push(b >> 8);
            }

            /**

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Enable 'Remove non-alphabet chars' to strip stray characters automatically.
  2. Clean the input to contain only alphabet characters before decoding.
  3. If using a custom alphabet, ensure it contains every character present in the input.

Example fix

// before: removal disabled, dirty input
fromBase45.run('GG5A-CC..\n', [ALPHABET, false]) // '-' not in alphabet
// after: enable removal or pre-clean
fromBase45.run('GG5A-CC..\n', [ALPHABET, true])
Defensive patterns

Strategy: validation

Validate before calling

// If removal is disabled, pre-filter input to alphabet chars only
const alphabet = Utils.expandAlphRange(args[0]).join('');
if (!args[1]) {
  input = input.split('').filter(c => alphabet.includes(c)).join('');
}

Type guard

function onlyAlphabetChars(s, alphabet) {
  return s.split('').every(c => alphabet.includes(c));
}

Try / catch

try {
  fromBase45.run(input, args);
} catch (e) {
  if (e.type === 'OperationError' && /Character not in alphabet/.test(e.message)) {
    // enable 'Remove non-alphabet chars' or clean the input
  } else throw e;
}

Prevention

When it happens

Trigger: Disabling 'Remove non-alphabet chars' and feeding input containing characters outside the Base45 alphabet [0-9A-Z space$%*+-./:]; a custom alphabet missing some characters present in the data; whitespace or delimiters not stripped.

Common situations: Decoding EU Digital COVID Certificate data with non-standard wrapping; whitespace/newlines in pasted input when removal is off; custom alphabet typo.

Related errors


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