gchq/CyberChef · error · OperationError
Ψ3 custom lugs must be 51 long and can only include . or x
Error message
Ψ3 custom lugs must be 51 long and can only include . or x
What it means
Thrown by the Lorenz operation only when 'Wheel Pattern' is 'Custom'. The Ψ3 wheel has 51 cams, so its lug pattern must be exactly 51 characters matching ^[.xX]*$. Guard is on line 284 of src/core/operations/Lorenz.mjs.
Source
Thrown at src/core/operations/Lorenz.mjs:284
if (s2<1 || s2>47) throw new OperationError("Ψ2 start must be between 1 and 47");
if (s3<1 || s3>51) throw new OperationError("Ψ3 start must be between 1 and 51");
if (s4<1 || s4>53) throw new OperationError("Ψ4 start must be between 1 and 53");
if (s5<1 || s5>59) throw new OperationError("Ψ5 start must be between 1 and 59");
if (m37<1 || m37>37) throw new OperationError("Μ37 start must be between 1 and 37");
if (m61<1 || m61>61) throw new OperationError("Μ61 start must be between 1 and 61");
if (x1<1 || x1>41) throw new OperationError("Χ1 start must be between 1 and 41");
if (x2<1 || x2>31) throw new OperationError("Χ2 start must be between 1 and 31");
if (x3<1 || x3>29) throw new OperationError("Χ3 start must be between 1 and 29");
if (x4<1 || x4>26) throw new OperationError("Χ4 start must be between 1 and 26");
if (x5<1 || x5>23) throw new OperationError("Χ5 start must be between 1 and 23");
// Initialise chosen wheel pattern
let chosenSetting = "";
if (pattern === "Custom") {
const re = new RegExp("^[.xX]*$");
if (lugs1.length !== 43 || !re.test(lugs1)) throw new OperationError("Ψ1 custom lugs must be 43 long and can only include . or x ");
if (lugs2.length !== 47 || !re.test(lugs2)) throw new OperationError("Ψ2 custom lugs must be 47 long and can only include . or x");
if (lugs3.length !== 51 || !re.test(lugs3)) throw new OperationError("Ψ3 custom lugs must be 51 long and can only include . or x");
if (lugs4.length !== 53 || !re.test(lugs4)) throw new OperationError("Ψ4 custom lugs must be 53 long and can only include . or x");
if (lugs5.length !== 59 || !re.test(lugs5)) throw new OperationError("Ψ5 custom lugs must be 59 long and can only include . or x");
if (lugm37.length !== 37 || !re.test(lugm37)) throw new OperationError("M37 custom lugs must be 37 long and can only include . or x");
if (lugm61.length !== 61 || !re.test(lugm61)) throw new OperationError("M61 custom lugs must be 61 long and can only include . or x");
if (lugx1.length !== 41 || !re.test(lugx1)) throw new OperationError("Χ1 custom lugs must be 41 long and can only include . or x");
if (lugx2.length !== 31 || !re.test(lugx2)) throw new OperationError("Χ2 custom lugs must be 31 long and can only include . or x");
if (lugx3.length !== 29 || !re.test(lugx3)) throw new OperationError("Χ3 custom lugs must be 29 long and can only include . or x");
if (lugx4.length !== 26 || !re.test(lugx4)) throw new OperationError("Χ4 custom lugs must be 26 long and can only include . or x");
if (lugx5.length !== 23 || !re.test(lugx5)) throw new OperationError("Χ5 custom lugs must be 23 long and can only include . or x");
chosenSetting = INIT_PATTERNS["No Pattern"];
chosenSetting.S[1] = this.readLugs(lugs1);
chosenSetting.S[2] = this.readLugs(lugs2);
chosenSetting.S[3] = this.readLugs(lugs3);
chosenSetting.S[4] = this.readLugs(lugs4);
chosenSetting.S[5] = this.readLugs(lugs5);
chosenSetting.M[1] = this.readLugs(lugm61);
chosenSetting.M[2] = this.readLugs(lugm37);
chosenSetting.X[1] = this.readLugs(lugx1);View on GitHub (pinned to 4290ea7539)
Solutions
- Provide a Ψ3 lugs string of exactly 51 characters using only '.', 'x', 'X'.
- Edit a known-good 51-character pattern in place rather than retyping.
- Pre-validate with /^[.xX]{51}$/ before running.
Example fix
// before: args[21] = "x" * 51 via wrong join (e.g. contains a space) -> throws // after: args[21] = ".x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x" (51 chars) -> ok
Defensive patterns
Strategy: validation
Validate before calling
// Ψ3 lugs (args[21]) must match /^[.xX]{51}$/ when pattern === 'Custom'.
function validateCustomLugs(str, size, name) {
if (typeof str !== "string" || !new RegExp(`^[.xX]{${size}}$`).test(str)) {
throw new Error(`${name} lugs must be exactly ${size} chars of '.', 'x', or 'X'`);
}
}
if (args[1] === "Custom") validateCustomLugs(args[21], 51, "Ψ3"); Type guard
const isPsi3Lugs = (s) => typeof s === "string" && /^[.xX]{51}$/.test(s); Try / catch
try {
lorenz.run(input, args);
} catch (err) {
if (err instanceof OperationError && /Ψ3 custom lugs/.test(err.message)) {
args[21] = ".x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x"; // known-good 51-char pattern
} else throw err;
} Prevention
- Ψ3 lug strings must be exactly 51 characters.
- Edit in place; avoid introducing whitespace or invalid chars.
- Validate with /^[.xX]{51}$/ before running.
When it happens
Trigger: Calling Lorenz.run() with pattern='Custom' where args[21] (Ψ3 lugs) is not exactly 51 characters or contains characters other than '.', 'x', 'X'.
Common situations: Custom pattern with a Ψ3 string of the wrong length (e.g. reused from Ψ1/Ψ2); invalid characters introduced during editing; trailing whitespace inflating length.
Related errors
- Ψ1 custom lugs must be 43 long and can only include . or x
- Ψ2 custom lugs must be 47 long and can only include . or x
- Ψ4 custom lugs must be 53 long and can only include . or x
- Ψ5 custom lugs must be 59 long and can only include . or x
- M37 custom lugs must be 37 long and can only include . or x
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/30c514bf918beb5f.
Report an issue: GitHub.