gchq/CyberChef · error · OperationError
Rotor wiring must have each letter exactly once
Error message
Rotor wiring must have each letter exactly once
What it means
Thrown by the Rotor constructor after building the wiring map: although wiring passed the 26-uppercase-letters format check, the letter set is not a permutation of A-Z (some letters repeat, others are absent). The code collects unique output letters into an object and requires all 26 to appear exactly once, which is what makes the rotor a bijection.
Source
Thrown at src/core/lib/Enigma.mjs:116
}
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;
uniq[b] = true;
}
if (Object.keys(uniq).length !== LETTERS.length) {
throw new OperationError("Rotor wiring must have each letter exactly once");
}
const rs = a2i(ringSetting);
this.steps = new Set();
for (const x of steps) {
this.steps.add(Utils.mod(a2i(x) - rs, 26));
}
if (this.steps.size !== steps.length) {
// This isn't strictly fatal, but it's probably a mistake
throw new OperationError("Rotor steps must be unique");
}
this.pos = Utils.mod(a2i(initialPosition) - rs, 26);
}
/**
* Step the rotor forward by one.
*/
step() {
this.pos = Utils.mod(this.pos + 1, 26);View on GitHub (pinned to 4290ea7539)
Solutions
- Ensure wiring is a permutation of the full alphabet (each letter A-Z exactly once).
- Validate new Set(wiring).size === 26 && wiring.length === 26 before constructing.
- Use a known-good rotor definition from the ROTORS table.
Example fix
// before
new Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCE', 'R', 'A', 'A'); // duplicate E, no J
// after
new Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 'A', 'A'); // valid permutation Defensive patterns
Strategy: validation
Validate before calling
function isPermutationOfAlphabet(wiring) {
return typeof wiring === "string" && wiring.length === 26 && new Set(wiring).size === 26 && /^[A-Z]+$/.test(wiring);
}
if (!isPermutationOfAlphabet(wiring)) {
throw new Error("Rotor wiring must be a permutation of A-Z.");
} Type guard
function isRotorWiringPermutation(s) {
return typeof s === "string" && s.length === 26 && new Set(s).size === 26 && /^[A-Z]+$/.test(s);
} Prevention
- Check Set size equals 26 in addition to the length/format regex.
- Prefer canonical ROTORS definitions over hand-typed wiring.
- Add a unit test asserting every letter A-Z appears once.
When it happens
Trigger: new Rotor(wiring, ...) where wiring is 26 uppercase letters but contains a duplicate (e.g. 'EKMFLGDQVZNTOWYHXUSPAIBRCE' with two E's and no J). The format regex passes but the uniqueness count fails.
Common situations: Hand-transcribed wiring with a typo duplicating a letter; copy-paste corruption; deliberately scrambled wiring that isn't a true permutation.
Related errors
- Rotor wiring must be 26 unique uppercase letters
- 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 steps must be unique
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/b0bebe4e39e00f9c.
Report an issue: GitHub.