{"record":{"id":"1f920573f4b0cbd8","repo":"gchq/CyberChef","slug":"a-minimum-of-three-rotors-must-be-supplied","errorCode":null,"errorMessage":"A minimum of three rotors must be supplied","messagePattern":"A minimum of three rotors must be supplied","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/MultipleBombe.mjs","lineNumber":198,"sourceCode":"     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        const mainRotorsStr = args[1];\n        const fourthRotorsStr = args[2];\n        const reflectorsStr = args[3];\n        let crib = args[4];\n        const offset = args[5];\n        const check = args[6];\n        const rotors = [];\n        const fourthRotors = [];\n        const reflectors = [];\n        for (let rstr of mainRotorsStr.split(\"\\n\")) {\n            rstr = this.validateRotor(rstr);\n            rotors.push(rstr);\n        }\n        if (rotors.length < 3) {\n            throw new OperationError(\"A minimum of three rotors must be supplied\");\n        }\n        if (fourthRotorsStr !== \"\") {\n            for (let rstr of fourthRotorsStr.split(\"\\n\")) {\n                rstr = this.validateRotor(rstr);\n                fourthRotors.push(rstr);\n            }\n        }\n        if (fourthRotors.length === 0) {\n            fourthRotors.push(\"\");\n        }\n        for (const rstr of reflectorsStr.split(\"\\n\")) {\n            const reflector = new Reflector(rstr);\n            reflectors.push(reflector);\n        }\n        if (reflectors.length === 0) {\n            throw new OperationError(\"A minimum of one reflector must be supplied\");\n        }\n        if (crib.length === 0) {","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/MultipleBombe.mjs#L180-L216","documentation":"Thrown by MultipleBombe.run when the main-rotors text area (args[1]) splits into fewer than 3 lines. The Bombe needs at least three rotors to search rotor orders, so fewer than three is an invalid configuration. Each line was already individually validated by validateRotor before this count check.","triggerScenarios":"run(input, args) where args[1].split('\\n').length < 3 — i.e. the main rotors field contains 0, 1, or 2 lines. An empty string still splits to [''] (length 1) and validateRotor will throw first on that empty line, so this specific error is reached when 1 or 2 valid rotors are supplied.","commonSituations":"User deleted rotor lines leaving only two; pasting a partial rotor set; recipe shared with a trimmed rotor field; misunderstanding that the field needs a pool of at least three rotors to choose from.","solutions":["Provide at least three rotor lines in the main-rotors field (the standard five Wehrmacht rotors I–V are typical).","Paste the canonical rotor set from the operation defaults.","Confirm there are no blank trailing lines that consume a slot."],"exampleFix":"// before (only 2 rotors)\nEKMFLGDQVZNTOWYHXUSPAIBRCJ\nAJDKSIRUXBLHINTMCYGFPZWOEV\n// after (add a third)\nEKMFLGDQVZNTOWYHXUSPAIBRCJ\nAJDKSIRUXBLHINTMCYGFPZWOEV\nBDFHJLCPRTXVZNYEIWGAKMUSQO","handlingStrategy":"validation","validationCode":"const mainRotorsStr = args[1];\nif (mainRotorsStr.split(\"\\n\").length < 3) {\n  // add more rotor lines before running\n}","typeGuard":"const hasMinThreeRotors = (s) => s.split(\"\\n\").length >= 3;","tryCatchPattern":"try { chef.bake(\"Multiple Bombe\", args); }\ncatch (e) { if (e.message === \"A minimum of three rotors must be supplied\") addRotors(); else throw e; }","preventionTips":["Keep the standard five-rotor pool (I–V) in the field.","Avoid deleting rotor lines below three.","Validate line count before baking."],"tags":["crypto","enigma","bombe","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}