{"record":{"id":"5d1e6f7c415920d9","repo":"gchq/CyberChef","slug":"typex-must-have-5-rotors","errorCode":null,"errorMessage":"Typex must have 5 rotors","messagePattern":"Typex must have 5 rotors","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Typex.mjs","lineNumber":60,"sourceCode":"for (const i of Object.keys(KEYBOARD)) {\n    KEYBOARD_REV[KEYBOARD[i]] = i;\n}\n\n/**\n * Typex machine. A lot like the Enigma, but five rotors, of which the first two are static.\n */\nexport class TypexMachine extends Enigma.EnigmaBase {\n    /**\n     * TypexMachine constructor.\n     *\n     * @param {Object[]} rotors - List of Rotors.\n     * @param {Object} reflector - A Reflector.\n     * @param {Plugboard} plugboard - A Plugboard.\n     */\n    constructor(rotors, reflector, plugboard, keyboard) {\n        super(rotors, reflector, plugboard);\n        if (rotors.length !== 5) {\n            throw new OperationError(\"Typex must have 5 rotors\");\n        }\n        this.keyboard = keyboard;\n    }\n\n    /**\n     * This is the same as the Enigma step function, it's just that the right-\n     * most two rotors are static.\n     */\n    step() {\n        const r0 = this.rotors[2];\n        const r1 = this.rotors[3];\n        r0.step();\n        // The second test here is the double-stepping anomaly\n        if (r0.steps.has(r0.pos) || r1.steps.has(Utils.mod(r1.pos + 1, 26))) {\n            r1.step();\n            if (r1.steps.has(r1.pos)) {\n                const r2 = this.rotors[4];\n                r2.step();","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Typex.mjs#L42-L78","documentation":"Thrown by the TypexMachine constructor in Typex.mjs when the rotors array does not contain exactly 5 entries. Typex is a five-rotor cipher machine (the right-most two rotors are static, the left three step), so any other count is a configuration error. The check runs after the superclass (EnigmaBase) constructor, so the rotor array must be valid Enigma rotors first.","triggerScenarios":"Constructing `new TypexMachine(rotors, reflector, plugboard, keyboard)` with rotors.length !== 5. Common: passing an Enigma-style 3-rotor array, omitting the two static rotors, or building the rotor list from a config that only listed the stepping rotors.","commonSituations":"Reusing Enigma rotor-setup code (3 rotors) for Typex; UI that only collects 3 rotor selections; config schema migrated from Enigma without adding the two static rotor slots.","solutions":["Provide exactly 5 rotors: rotors[0] and rotors[1] are static, rotors[2..4] step. Order is left-to-right as for Enigma.","If migrating Enigma config, append two valid static rotors (any valid rotor wiring; they do not step).","Validate rotors.length === 5 before constructing so the error is caught at config-load time with a clearer message."],"exampleFix":"// before: only 3 rotors supplied\nnew TypexMachine([r1, r2, r3], reflector, plugboard, \"Encrypt\");\n// after: 5 rotors, first two static\nnew TypexMachine([static1, static2, r1, r2, r3], reflector, plugboard, \"Encrypt\");","handlingStrategy":"validation","validationCode":"if (!Array.isArray(rotors) || rotors.length !== 5) {\n    throw new Error(\n        `Typex requires exactly 5 rotors (2 static + 3 stepping). Got ${rotors?.length}.`\n    );\n}\nconst machine = new TypexMachine(rotors, reflector, plugboard, keyboard);","typeGuard":"function isTypexRotorSet(rotors) {\n    return Array.isArray(rotors) && rotors.length === 5;\n}","tryCatchPattern":"try {\n    machine = new TypexMachine(rotors, reflector, plugboard, keyboard);\n} catch (e) {\n    if (e instanceof OperationError && /Typex must have 5 rotors/.test(e.message)) {\n        return { error: `Configure 5 Typex rotors (first two static) instead of ${rotors.length}.` };\n    }\n    throw e;\n}","preventionTips":["Build rotor arrays from a Typex-specific config schema that has 5 slots, not the 3-slot Enigma schema.","Validate the count at config load, before constructing the machine.","Remember rotors[0] and rotors[1] are static; rotors[2..4] step."],"tags":["crypto","typex","rotor-config","argument-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}