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 MultipleBombe.validateRotor when a rotor wiring string (after stripping any '<stepping>' suffix) does not match /^[A-Z]{26}$/. Each Enigma rotor must be a permutation expressed as exactly 26 uppercase ASCII letters. Failing this regex means wrong length, lowercase, digits, or non-letters.
Source
Thrown at src/core/operations/MultipleBombe.mjs:170
const msg = `Bombe run with ${nLoops} loop${nLoops === 1 ? "" : "s"} in menu (2+ desirable): ${nStops} stops, ${Math.floor(100 * progress)}% done, ${hours}:${minutes}:${seconds} remaining`;
self.sendStatusMessage(msg);
}
/**
* Early rotor description string validation.
* Drops stepping information.
* @param {string} rstr - The rotor description string
* @returns {string} - Rotor description with stepping stripped, if any
*/
validateRotor(rstr) {
// The Bombe doesn't take stepping into account so we'll just ignore it here
if (rstr.includes("<")) {
rstr = rstr.split("<", 2)[0];
}
// Duplicate the validation of the rotor strings here, otherwise you might get an error
// thrown halfway into a big Bombe run
if (!/^[A-Z]{26}$/.test(rstr)) {
throw new OperationError("Rotor wiring must be 26 unique uppercase letters");
}
if (new Set(rstr).size !== 26) {
throw new OperationError("Rotor wiring must be 26 unique uppercase letters");
}
return rstr;
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const mainRotorsStr = args[1];
const fourthRotorsStr = args[2];
const reflectorsStr = args[3];
let crib = args[4];
const offset = args[5];View on GitHub (pinned to 4290ea7539)
Solutions
- Supply exactly 26 uppercase A-Z characters per rotor line, e.g. 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.
- Strip any label/prefix and uppercase the string before pasting.
- Use the canonical Wehrmacht/Naval rotor definitions from the operation's default values.
Example fix
// before EKMFLGDQVZNTOWYHXUSPAIBRC // 25 letters -> regex fail // after EKMFLGDQVZNTOWYHXUSPAIBRCJ // 26 letters
Defensive patterns
Strategy: validation
Validate before calling
function validRotorShape(rstr) {
if (rstr.includes("<")) rstr = rstr.split("<", 2)[0];
return /^[A-Z]{26}$/.test(rstr);
} Type guard
const isRotorShaped = (rstr) =>
/^[A-Z]{26}$/.test(rstr.includes("<") ? rstr.split("<", 2)[0] : rstr); Try / catch
try { chef.bake("Multiple Bombe", args); }
catch (e) { if (e.message.startsWith("Rotor wiring must be")) fixRotorLines(); else throw e; } Prevention
- Always paste canonical rotor definitions.
- Strip labels and uppercase before pasting.
- Validate each line is exactly 26 A-Z chars.
When it happens
Trigger: validateRotor(rstr) called on any line of the main-rotors or fourth-rotor text areas where the line is not exactly 26 chars of A-Z (e.g. 25 letters, lowercase, contains a digit, contains a space, or empty line). The check fires early so a malformed rotor fails before a long Bombe run.
Common situations: Typo in a hand-entered rotor; pasting rotors that include a leading label like 'I:'; trailing carriage returns producing a 27-char line; lowercase paste from a documentation site; missing one letter.
Related errors
- A minimum of three rotors must be supplied
- A minimum of one reflector must be supplied
- Crib cannot be empty
- Offset cannot be negative
- ${name} connects ${pair[1]} more than once
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/b83293d53b51540d.
Report an issue: GitHub.