{"record":{"id":"64a5de51443338a6","repo":"gchq/CyberChef","slug":"rotor-wiring-must-be-26-unique-uppercase-letters","errorCode":null,"errorMessage":"Rotor wiring must be 26 unique uppercase letters","messagePattern":"Rotor wiring must be 26 unique uppercase letters","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Enigma.mjs","lineNumber":94,"sourceCode":"    }\n    throw new OperationError(\"i2a called on value outside 0..25\");\n}\n\n/**\n * A rotor in the Enigma machine.\n */\nexport class Rotor {\n    /**\n     * Rotor constructor.\n     *\n     * @param {string} wiring - A 26 character string of the wiring order.\n     * @param {string} steps - A 0..26 character string of stepping points.\n     * @param {char} ringSetting - The ring setting.\n     * @param {char} initialPosition - The initial position of the rotor.\n     */\n    constructor(wiring, steps, ringSetting, initialPosition) {\n        if (!/^[A-Z]{26}$/.test(wiring)) {\n            throw new OperationError(\"Rotor wiring must be 26 unique uppercase letters\");\n        }\n        if (!/^[A-Z]{0,26}$/.test(steps)) {\n            throw new OperationError(\"Rotor steps must be 0-26 unique uppercase letters\");\n        }\n        if (!/^[A-Z]$/.test(ringSetting)) {\n            throw new OperationError(\"Rotor ring setting must be exactly one uppercase letter\");\n        }\n        if (!/^[A-Z]$/.test(initialPosition)) {\n            throw new OperationError(\"Rotor initial position must be exactly one uppercase letter\");\n        }\n        this.map = new Array(26);\n        this.revMap = new Array(26);\n        const uniq = {};\n        for (let i=0; i<LETTERS.length; i++) {\n            const a = a2i(LETTERS[i]);\n            const b = a2i(wiring[i]);\n            this.map[a] = b;\n            this.revMap[b] = a;","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Enigma.mjs#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnew Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ<R', 'R', 'A', 'A'); // 28 chars incl '<R'\n\n// after\nnew Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 'A', 'A');","handlingStrategy":"validation","validationCode":"function normaliseRotorValue(value) {\n  // ROTORS entries look like 'EKMFLGDQVZNTOWYHXUSPAIBRCJ<R'\n  return value.split(\"<\")[0];\n}\nconst wiring = normaliseRotorValue(rotorValue);\nif (!/^[A-Z]{26}$/.test(wiring)) {\n  throw new Error(\"Rotor wiring must be exactly 26 uppercase letters.\");\n}\nnew Rotor(wiring, steps, ringSetting, initialPosition);","typeGuard":"function isRotorWiringFormat(s) {\n  return typeof s === \"string\" && /^[A-Z]{26}$/.test(s);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["enigma","cryptography","input-validation","rotor"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}