gchq/CyberChef · error · OperationError
Rotor wiring must be 26 unique uppercase letters
Error message
Rotor wiring must be 26 unique uppercase letters
What it means
Thrown by the Rotor constructor when the wiring argument fails /^[A-Z]{26}$/ — i.e. it is not exactly 26 uppercase ASCII letters. This is the first format gate before uniqueness is checked; length, case, and character class are all enforced here.
Source
Thrown at src/core/lib/Enigma.mjs:94
}
throw new OperationError("i2a called on value outside 0..25");
}
/**
* A rotor in the Enigma machine.
*/
export class Rotor {
/**
* Rotor constructor.
*
* @param {string} wiring - A 26 character string of the wiring order.
* @param {string} steps - A 0..26 character string of stepping points.
* @param {char} ringSetting - The ring setting.
* @param {char} initialPosition - The initial position of the rotor.
*/
constructor(wiring, steps, ringSetting, initialPosition) {
if (!/^[A-Z]{26}$/.test(wiring)) {
throw new OperationError("Rotor wiring must be 26 unique uppercase letters");
}
if (!/^[A-Z]{0,26}$/.test(steps)) {
throw new OperationError("Rotor steps must be 0-26 unique uppercase letters");
}
if (!/^[A-Z]$/.test(ringSetting)) {
throw new OperationError("Rotor ring setting must be exactly one uppercase letter");
}
if (!/^[A-Z]$/.test(initialPosition)) {
throw new OperationError("Rotor initial position must be exactly one uppercase letter");
}
this.map = new Array(26);
this.revMap = new Array(26);
const uniq = {};
for (let i=0; i<LETTERS.length; i++) {
const a = a2i(LETTERS[i]);
const b = a2i(wiring[i]);
this.map[a] = b;
this.revMap[b] = a;View on GitHub (pinned to 4290ea7539)
Solutions
- Pass only the 26-letter wiring portion; strip anything from '<' onward (e.g. value.split('<')[0]).
- Ensure wiring is exactly 26 uppercase A-Z characters.
- Validate against /^[A-Z]{26}$/ before constructing the Rotor.
Example fix
// before
new Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ<R', 'R', 'A', 'A'); // 28 chars incl '<R'
// after
new Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 'A', 'A'); Defensive patterns
Strategy: validation
Validate before calling
function normaliseRotorValue(value) {
// ROTORS entries look like 'EKMFLGDQVZNTOWYHXUSPAIBRCJ<R'
return value.split("<")[0];
}
const wiring = normaliseRotorValue(rotorValue);
if (!/^[A-Z]{26}$/.test(wiring)) {
throw new Error("Rotor wiring must be exactly 26 uppercase letters.");
}
new Rotor(wiring, steps, ringSetting, initialPosition); Type guard
function isRotorWiringFormat(s) {
return typeof s === "string" && /^[A-Z]{26}$/.test(s);
} Prevention
- Always strip the '<...' step suffix from ROTORS values before passing as wiring.
- Keep a single helper that splits a ROTORS value into {wiring, steps}.
- Validate the 26-uppercase regex before constructing.
When it happens
Trigger: new Rotor(wiring, ...) where wiring is fewer/more than 26 chars, contains lowercase letters, digits, the stepping marker '<', whitespace, or non-ASCII. Commonly happens when passing a full ROTORS value string like 'EKMFLGDQVZNTOWYHXUSPAIBRCJ<R' as wiring without stripping the '<R' suffix.
Common situations: Passing the raw 'value' field from the ROTORS table (which appends '<' and step letters) directly as wiring; truncated/copied wiring strings; lowercase input; off-by-one length from a manual transcription.
Related errors
- Rotor steps must be 0-26 unique uppercase letters
- Rotor ring setting must be exactly one uppercase letter
- Rotor initial position must be exactly one uppercase letter
- Rotor wiring must have each letter exactly once
- Rotor steps must be unique
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/64a5de51443338a6.
Report an issue: GitHub.