gchq/CyberChef · error · OperationError

Ψ4 start must be between 1 and 53

Error message

Ψ4 start must be between 1 and 53

What it means

Thrown by the Lorenz operation when the Ψ4 wheel start position is out of range. The Ψ4 wheel has 53 cams, so the 1-indexed start must be in [1, 53]. Guard is on line 268 of src/core/operations/Lorenz.mjs.

Source

Thrown at src/core/operations/Lorenz.mjs:268

        let s1 = args[7],
            s2 = args[8],
            s3 = args[9],
            s4 = args[10],
            s5 = args[11],
            m37 = args[12],
            m61 = args[13],
            x1 = args[14],
            x2 = args[15],
            x3 = args[16],
            x4 = args[17],
            x5 = args[18];

        this.reverseTable();

        if (s1<1 || s1>43) throw new OperationError("Ψ1 start must be between 1 and 43");
        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");

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Set the Ψ4 start argument to an integer in [1, 53].
  2. Clamp generated values with `((n - 1) % 53) + 1`.
  3. Reset all wheel-start fields to 1 and re-enter intended offsets.

Example fix

// before: args[10] = 54  -> throws
// after:  args[10] = 1   -> ok
Defensive patterns

Strategy: validation

Validate before calling

// Ψ4 start (args[10]) must be in [1, 53]
function clampWheelStart(n, size) {
  if (!Number.isFinite(n)) throw new Error(`start must be a number, got ${n}`);
  return ((Math.floor(n) - 1) % size + size) % size + 1;
}
args[10] = clampWheelStart(args[10], 53);

Type guard

const isPsi4Start = (v) => Number.isInteger(v) && v >= 1 && v <= 53;

Try / catch

try {
  lorenz.run(input, args);
} catch (err) {
  if (err instanceof OperationError && /Ψ4 start/.test(err.message)) {
    args[10] = 1;
  } else throw err;
}

Prevention

When it happens

Trigger: Calling Lorenz.run() with args[10] ('Ψ4 start (1-53)') less than 1 or greater than 53.

Common situations: Wheel defaulted to 0; value copied from another wheel's larger range; recipe with a typo'd position.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/e4548dab6d4544d0. Report an issue: GitHub.