gchq/CyberChef · error · OperationError
err.message.replace("Rotor", "Plugboard")
Error message
err.message.replace("Rotor", "Plugboard") What it means
Thrown by the Typex Plugboard constructor in Typex.mjs in the catch block: when the mirrored wiring passes the regex but the Enigma Rotor superclass rejects it (typically because the 26 letters are not a unique permutation), the constructor rewrites the superclass error message, replacing the substring "Rotor" with "Plugboard" and re-throws as an OperationError. So the literal thrown text is dynamic — it is whatever the rotor error said, with 'Rotor' swapped for 'Plugboard' (e.g. 'Plugboard wiring must be 26 unique letters').
Source
Thrown at src/core/lib/Typex.mjs:204
// Typex input wiring is backwards vs Enigma: that is, letters enter the rotors in a
// clockwise order, vs. Enigma's anticlockwise (or vice versa depending on which side
// you're looking at it from). I'm doing the transform here to avoid having to rewrite
// the Engima crypt() method in Typex as well.
// Note that the wiring for the reflector is the same way around as Enigma, so no
// transformation is necessary on that side.
// We're going to achieve this by mapping the plugboard settings through an additional
// transform that mirrors the alphabet before we pass it to the superclass.
if (!/^[A-Z]{26}$/.test(wiring)) {
throw new OperationError("Plugboard wiring must be 26 unique uppercase letters");
}
const reversed = "AZYXWVUTSRQPONMLKJIHGFEDCB";
wiring = wiring.replace(/./g, x => {
return reversed[Enigma.a2i(x)];
});
try {
super(wiring, "", "A", "A");
} catch (err) {
throw new OperationError(err.message.replace("Rotor", "Plugboard"));
}
}
/**
* Transform a character through this rotor forwards.
*
* @param {number} c - The character.
* @returns {number}
*/
transform(c) {
return Utils.mod(this.map[Utils.mod(c + this.pos, 26)] - this.pos, 26);
}
/**
* Transform a character through this rotor backwards.
*
* @param {number} c - The character.
* @returns {number}View on GitHub (pinned to 4290ea7539)
Solutions
- Ensure the wiring is a true permutation: every letter A-Z appears exactly once. Check with new Set(wiring).size === 26.
- If you want a pass-through plugboard, use the identity "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
- Generate wirings with a verified shuffle of the alphabet rather than ad-hoc string building.
Example fix
// before: 'A' repeated, 'Z' missing
new Plugboard("ABCDEFGHIJKLMNOPQRSTUVAWXYZ"); // superclass throws, rewritten
// after: true permutation
new Plugboard("AYZXWVUTSRQPONMLKJIHGFEDCB"); Defensive patterns
Strategy: validation
Validate before calling
function isAlphabetPermutation(w) {
if (typeof w !== "string" || w.length !== 26) return false;
const seen = new Set();
for (const ch of w) {
if (ch < "A" || ch > "Z") return false;
if (seen.has(ch)) return false;
seen.add(ch);
}
return seen.size === 26;
}
if (!isAlphabetPermutation(wiring)) {
throw new Error(
`Plugboard wiring must be a permutation of A-Z (each letter exactly once). Got: '${wiring}'.`
);
}
new Typex.Plugboard(wiring); Type guard
function isAlphabetPermutation(w) {
if (typeof w !== "string" || w.length !== 26) return false;
const seen = new Set();
for (const ch of w) {
if (ch < "A" || ch > "Z") return false;
if (seen.has(ch)) return false;
seen.add(ch);
}
return seen.size === 26;
} Try / catch
try {
plugboard = new Typex.Plugboard(wiring);
} catch (e) {
if (e instanceof OperationError && /Plugboard/i.test(e.message)) {
// message is the rewritten rotor error; surface a clearer one
return { error: `Plugboard wiring must be a permutation of A-Z (no repeats).` };
}
throw e;
} Prevention
- Generate wirings with a verified Fisher-Yates shuffle of the alphabet, never by ad-hoc string building.
- Check new Set(wiring).size === 26 at the config boundary to catch repeats early.
- For no-plugboard behaviour, use the identity alphabet string.
When it happens
Trigger: Constructing `new Typex.Plugboard(wiring)` with a 26-uppercase-letter string that is NOT a permutation of A-Z — i.e. it has duplicate letters and is missing others. The regex at line 194 passes (right length and charset) but the superclass uniqueness check fails, and this catch fires.
Common situations: Hand-typed wiring with a repeated letter (e.g. two 'A's); wiring generated by a buggy permutation routine that can repeat; copy-paste that duplicated a letter; an intentional non-bijective map that Typex (via Enigma) does not allow.
Related errors
- Plugboard wiring must be 26 unique uppercase letters
- Typex must have 5 rotors
- ${name} must be a whitespace-separated list of uppercase let
- ${name} connects ${pair[0]} more than once
- ${name} connects ${pair[1]} more than once
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/c7a8c19063e68caf.
Report an issue: GitHub.