{"record":{"id":"ca2c811c8478125e","repo":"gchq/CyberChef","slug":"1-custom-lugs-must-be-43-long-and-can-only-includ","errorCode":null,"errorMessage":"Ψ1 custom lugs must be 43 long and can only include . or x ","messagePattern":"Ψ1 custom lugs must be 43 long and can only include \\. or x ","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/Lorenz.mjs","lineNumber":282,"sourceCode":"\n        if (s1<1 || s1>43) throw new OperationError(\"Ψ1 start must be between 1 and 43\");\n        if (s2<1 || s2>47) throw new OperationError(\"Ψ2 start must be between 1 and 47\");\n        if (s3<1 || s3>51) throw new OperationError(\"Ψ3 start must be between 1 and 51\");\n        if (s4<1 || s4>53) throw new OperationError(\"Ψ4 start must be between 1 and 53\");\n        if (s5<1 || s5>59) throw new OperationError(\"Ψ5 start must be between 1 and 59\");\n        if (m37<1 || m37>37) throw new OperationError(\"Μ37 start must be between 1 and 37\");\n        if (m61<1 || m61>61) throw new OperationError(\"Μ61 start must be between 1 and 61\");\n        if (x1<1 || x1>41) throw new OperationError(\"Χ1 start must be between 1 and 41\");\n        if (x2<1 || x2>31) throw new OperationError(\"Χ2 start must be between 1 and 31\");\n        if (x3<1 || x3>29) throw new OperationError(\"Χ3 start must be between 1 and 29\");\n        if (x4<1 || x4>26) throw new OperationError(\"Χ4 start must be between 1 and 26\");\n        if (x5<1 || x5>23) throw new OperationError(\"Χ5 start must be between 1 and 23\");\n\n        // Initialise chosen wheel pattern\n        let chosenSetting = \"\";\n        if (pattern === \"Custom\") {\n            const re = new RegExp(\"^[.xX]*$\");\n            if (lugs1.length !== 43 || !re.test(lugs1)) throw new OperationError(\"Ψ1 custom lugs must be 43 long and can only include . or x \");\n            if (lugs2.length !== 47 || !re.test(lugs2)) throw new OperationError(\"Ψ2 custom lugs must be 47 long and can only include . or x\");\n            if (lugs3.length !== 51 || !re.test(lugs3)) throw new OperationError(\"Ψ3 custom lugs must be 51 long and can only include . or x\");\n            if (lugs4.length !== 53 || !re.test(lugs4)) throw new OperationError(\"Ψ4 custom lugs must be 53 long and can only include . or x\");\n            if (lugs5.length !== 59 || !re.test(lugs5)) throw new OperationError(\"Ψ5 custom lugs must be 59 long and can only include . or x\");\n            if (lugm37.length !== 37 || !re.test(lugm37)) throw new OperationError(\"M37 custom lugs must be 37 long and can only include . or x\");\n            if (lugm61.length !== 61 || !re.test(lugm61)) throw new OperationError(\"M61 custom lugs must be 61 long and can only include . or x\");\n            if (lugx1.length !== 41 || !re.test(lugx1)) throw new OperationError(\"Χ1 custom lugs must be 41 long and can only include . or x\");\n            if (lugx2.length !== 31 || !re.test(lugx2)) throw new OperationError(\"Χ2 custom lugs must be 31 long and can only include . or x\");\n            if (lugx3.length !== 29 || !re.test(lugx3)) throw new OperationError(\"Χ3 custom lugs must be 29 long and can only include . or x\");\n            if (lugx4.length !== 26 || !re.test(lugx4)) throw new OperationError(\"Χ4 custom lugs must be 26 long and can only include . or x\");\n            if (lugx5.length !== 23 || !re.test(lugx5)) throw new OperationError(\"Χ5 custom lugs must be 23 long and can only include . or x\");\n            chosenSetting = INIT_PATTERNS[\"No Pattern\"];\n            chosenSetting.S[1] = this.readLugs(lugs1);\n            chosenSetting.S[2] = this.readLugs(lugs2);\n            chosenSetting.S[3] = this.readLugs(lugs3);\n            chosenSetting.S[4] = this.readLugs(lugs4);\n            chosenSetting.S[5] = this.readLugs(lugs5);\n            chosenSetting.M[1] = this.readLugs(lugm61);","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/Lorenz.mjs#L264-L300","documentation":"Thrown by the Lorenz operation only when 'Wheel Pattern' is set to 'Custom'. Each wheel's lug (cam) pattern must be a string of exactly the wheel's cam count, using '.' for an inactive lug and 'x' or 'X' for an active one. Ψ1 has 43 cams, so its pattern must be exactly 43 characters matching ^[.xX]*$. Guard is on line 282 of src/core/operations/Lorenz.mjs.","triggerScenarios":"Calling Lorenz.run() with pattern='Custom' where args[19] (the Ψ1 lugs string) has a length other than 43, or contains characters other than '.', 'x', 'X' (e.g. spaces, 'o', '0', '-').","commonSituations":"Switching to Custom pattern but leaving default KH-pattern strings that are the wrong length; copy-paste truncating the string; using 'O' or '0' instead of 'x'; editing one wheel and forgetting the others all need valid strings too.","solutions":["Provide a Ψ1 lugs string of exactly 43 characters composed only of '.', 'x', 'X'.","If you only want to tweak an existing pattern, start from the default value and change individual characters without altering the length.","Validate every Custom lug string with a regex ^[.xX]{N}$ where N is the wheel's cam count before running."],"exampleFix":"// before: args[19] = \"x.x\"                       (too short) -> throws\n// after:  args[19] = \".x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x\"  (43 chars) -> ok","handlingStrategy":"validation","validationCode":"// Only matters when pattern === 'Custom'. Ψ1 lugs (args[19]) must match /^[.xX]{43}$/.\nfunction validateCustomLugs(str, size, name) {\n  if (typeof str !== \"string\" || !new RegExp(`^[.xX]{${size}}$`).test(str)) {\n    throw new Error(`${name} lugs must be exactly ${size} chars of '.', 'x', or 'X'`);\n  }\n}\nif (args[1] === \"Custom\") validateCustomLugs(args[19], 43, \"Ψ1\");","typeGuard":"const isPsi1Lugs = (s) => typeof s === \"string\" && /^[.xX]{43}$/.test(s);","tryCatchPattern":"try {\n  lorenz.run(input, args);\n} catch (err) {\n  if (err instanceof OperationError && /Ψ1 custom lugs/.test(err.message)) {\n    args[19] = \".x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x\"; // known-good 43-char pattern\n  } else throw err;\n}","preventionTips":["Only validate lug strings when the Wheel Pattern is 'Custom'; named patterns supply their own.","Edit a known-good pattern in place to avoid length errors.","Use only '.', 'x', 'X' — never 'O', '0', '-', or spaces."],"tags":["lorenz","custom-pattern","lug-validation","argument-validation","rotor-cipher","string-format"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}