{"record":{"id":"cd6d5a03d56eabca","repo":"gchq/CyberChef","slug":"rotor-initial-position-must-be-exactly-one-upperca","errorCode":null,"errorMessage":"Rotor initial position must be exactly one uppercase letter","messagePattern":"Rotor initial position must be exactly one uppercase letter","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Enigma.mjs","lineNumber":103,"sourceCode":"     * 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;\n            uniq[b] = true;\n        }\n        if (Object.keys(uniq).length !== LETTERS.length) {\n            throw new OperationError(\"Rotor wiring must have each letter exactly once\");\n        }\n        const rs = a2i(ringSetting);\n        this.steps = new Set();\n        for (const x of steps) {\n            this.steps.add(Utils.mod(a2i(x) - rs, 26));","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Enigma.mjs#L85-L121","documentation":"Thrown by the Rotor constructor when initialPosition fails /^[A-Z]$/ — it must be exactly one uppercase ASCII letter representing the rotor's starting window position.","triggerScenarios":"new Rotor(..., initialPosition) where initialPosition is empty, longer than one char, lowercase, a number (e.g. the common numeric 1-26 convention), or undefined.","commonSituations":"Passing a numeric starting position from historical settings tables instead of the letter A-Z; empty/undefined value; lowercase input.","solutions":["Convert numeric positions to letters: String.fromCharCode(64 + n) for n in 1-26.","Pass exactly one uppercase letter.","Validate /^[A-Z]$/.test(initialPosition) before constructing."],"exampleFix":"// before\nnew Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 'A', 1); // number\n\n// after\nnew Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 'A', 'A');","handlingStrategy":"validation","validationCode":"function positionToLetter(n) {\n  if (!Number.isInteger(n) || n < 1 || n > 26) throw new Error(\"Position must be 1-26.\");\n  return String.fromCharCode(64 + n);\n}\nconst initialPosition = positionToLetter(numericPos);\nif (!/^[A-Z]$/.test(initialPosition)) {\n  throw new Error(\"Initial position must be one uppercase letter.\");\n}","typeGuard":"function isSingleUppercaseLetter(c) {\n  return typeof c === \"string\" && /^[A-Z]$/.test(c);\n}","tryCatchPattern":null,"preventionTips":["Convert numeric positions (1-26) to letters before constructing.","Pass exactly one uppercase letter.","Validate /^[A-Z]$/ beforehand."],"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"}