gchq/CyberChef · error · OperationError

Error: all numbers must be between 1 and 26.

Error message

Error: all numbers must be between 1 and 26.

What it means

A1Z26 is a substitution cipher mapping 1→a, 2→b, … 26→z. The decoder splits the input string on a chosen delimiter and expects every resulting token to be an integer in the closed range [1, 26]. This OperationError is thrown inside the run loop when any token falls outside that range (note the comparison coerces the string token to a number, so an empty token becomes 0 and also trips the guard).

Source

Thrown at src/core/operations/A1Z26CipherDecode.mjs:86

    }

    /**
     * @param {string} input
     * @param {Object[]} args
     * @returns {string}
     */
    run(input, args) {
        const delim = Utils.charRep(args[0] || "Space");

        if (input.length === 0) {
            return "";
        }

        const bites = input.split(delim);
        let latin1 = "";
        for (let i = 0; i < bites.length; i++) {
            if (bites[i] < 1 || bites[i] > 26) {
                throw new OperationError("Error: all numbers must be between 1 and 26.");
            }
            latin1 += Utils.chr(parseInt(bites[i], 10) + 96);
        }
        return latin1;
    }

}

export default A1Z26CipherDecode;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Normalize the input: trim it and collapse repeated delimiters before running, e.g. input.trim().replace(/ +/g, ' ').
  2. Confirm the delimiter argument (args[0]) matches the one used when the text was encoded.
  3. Filter out empty tokens and any value outside 1–26 if you are preprocessing a noisy source.
  4. If the data legitimately contains numbers outside 1–26 or non-numeric symbols, A1Z26 is the wrong operation — use From Decimal or a custom parser instead.

Example fix

// before: input "1 2 27 " throws on 27 and trailing empty token
// after: pre-validate / sanitize
const clean = input.trim().split(/\s+/).filter(t => t !== '').join(' ');
// then run A1Z26CipherDecode on clean
Defensive patterns

Strategy: validation

Validate before calling

function validateA1Z26Input(input, delim) {
  const tokens = input.split(delim).filter(t => t.length > 0);
  for (const t of tokens) {
    const n = Number(t);
    if (!Number.isInteger(n) || n < 1 || n > 26) {
      throw new Error(`Token '${t}' is not an integer in [1,26]`);
    }
  }
  return tokens.join(delim);
}

Type guard

function isA1Z26Token(t) {
  const n = Number(t);
  return Number.isInteger(n) && n >= 1 && n <= 26;
}

Try / catch

try {
  runA1Z26(input, delim);
} catch (e) {
  if (/between 1 and 26/.test(e.message)) {
    // sanitize and retry, or surface to user
  } else throw e;
}

Prevention

When it happens

Trigger: Calling run() on input where any split token is < 1 or > 26. Concretely: a value of 0, 27, or a negative; an empty token produced by a leading/trailing/doubled delimiter (e.g. "1 2 " or "1 2" with Space delim yields ""); a non-numeric token that coerces to 0 (though non-numeric/NaN tokens actually slip past the range check and then break Utils.chr).

Common situations: Input pasted with a trailing space or double spaces; wrong delimiter selected (encoder used comma but decoder uses space); numbers exceeding 26 because the data is not actually A1Z26-encoded; mixing punctuation or whitespace into the token stream.

Related errors


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