{"record":{"id":"ba8453dcddc89eb4","repo":"gchq/CyberChef","slug":"rotor-ring-setting-must-be-exactly-one-uppercase-l","errorCode":null,"errorMessage":"Rotor ring setting must be exactly one uppercase letter","messagePattern":"Rotor ring setting must be exactly one uppercase letter","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Enigma.mjs","lineNumber":100,"sourceCode":" */\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;\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);","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Enigma.mjs#L82-L118","documentation":"Thrown by the Rotor constructor when ringSetting fails /^[A-Z]$/ — it must be exactly one uppercase ASCII letter. The ring setting offsets the wiring relative to the alphabet and is combined with the step positions.","triggerScenarios":"new Rotor(..., ringSetting, ...) where ringSetting is an empty string, more than one character, lowercase, a number, or a multi-char string like 'AA'.","commonSituations":"Passing a numeric ring setting (common in Enigma literature where ring settings are 1-26) instead of the letter A-Z; passing an empty value; case mismatch.","solutions":["Convert numeric ring settings to a letter: String.fromCharCode(64 + n) for n in 1-26 (so 1 -> 'A').","Pass exactly one uppercase letter.","Validate /^[A-Z]$/.test(ringSetting) before constructing."],"exampleFix":"// before\nnew Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 1, 'A'); // number, not letter\n\n// after\nnew Rotor('EKMFLGDQVZNTOWYHXUSPAIBRCJ', 'R', 'A', 'A');","handlingStrategy":"validation","validationCode":"function ringSettingToLetter(n) {\n  if (!Number.isInteger(n) || n < 1 || n > 26) throw new Error(\"Ring setting must be 1-26.\");\n  return String.fromCharCode(64 + n);\n}\nconst ringSetting = ringSettingToLetter(numericRing);\nif (!/^[A-Z]$/.test(ringSetting)) {\n  throw new Error(\"Ring setting 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 ring settings (1-26) to letters before constructing.","Always 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"}