{"record":{"id":"c7110fdd7ff48d29","repo":"gchq/CyberChef","slug":"4-custom-lugs-must-be-53-long-and-can-only-includ","errorCode":null,"errorMessage":"Ψ4 custom lugs must be 53 long and can only include . or x","messagePattern":"Ψ4 custom lugs must be 53 long and can only include \\. or x","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/Lorenz.mjs","lineNumber":285,"sourceCode":"        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);\n            chosenSetting.M[2] = this.readLugs(lugm37);\n            chosenSetting.X[1] = this.readLugs(lugx1);\n            chosenSetting.X[2] = this.readLugs(lugx2);","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/Lorenz.mjs#L267-L303","documentation":"Thrown by the Lorenz operation only when 'Wheel Pattern' is 'Custom'. The Ψ4 wheel has 53 cams, so its lug pattern must be exactly 53 characters matching ^[.xX]*$. Guard is on line 285 of src/core/operations/Lorenz.mjs.","triggerScenarios":"Calling Lorenz.run() with pattern='Custom' where args[22] (Ψ4 lugs) is not exactly 53 characters or contains characters other than '.', 'x', 'X'.","commonSituations":"Custom pattern with a Ψ4 string of the wrong length; a stray character or whitespace added during edit; pattern copied from Ψ3 (51) or Ψ5 (59).","solutions":["Provide a Ψ4 lugs string of exactly 53 characters using only '.', 'x', 'X'.","Edit a known-good 53-character pattern in place.","Pre-validate with /^[.xX]{53}$/ before running."],"exampleFix":"// before: args[22] = \"...x\" (4 chars) -> throws\n// after:  args[22] = \".xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x.\"  (53 chars) -> ok","handlingStrategy":"validation","validationCode":"// Ψ4 lugs (args[22]) must match /^[.xX]{53}$/ when pattern === 'Custom'.\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[22], 53, \"Ψ4\");","typeGuard":"const isPsi4Lugs = (s) => typeof s === \"string\" && /^[.xX]{53}$/.test(s);","tryCatchPattern":"try {\n  lorenz.run(input, args);\n} catch (err) {\n  if (err instanceof OperationError && /Ψ4 custom lugs/.test(err.message)) {\n    args[22] = \".xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x.\"; // known-good 53-char pattern\n  } else throw err;\n}","preventionTips":["Ψ4 lug strings must be exactly 53 characters (the longest psi wheel along with Ψ5's 59).","Edit in place; watch for accidental truncation.","Validate with /^[.xX]{53}$/ before running."],"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"}