{"record":{"id":"0dbabc580d8b0cd7","repo":"gchq/CyberChef","slug":"modulus-m-must-be-defined","errorCode":null,"errorMessage":"Modulus (m) must be defined","messagePattern":"Modulus \\(m\\) must be defined","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/ModularInverse.mjs","lineNumber":77,"sourceCode":"        const mParam = mStr?.trim();\n        const inputVal = input?.trim();\n\n        let a, m;\n\n        if (aParam && mParam) {\n            // Case 1: value and modulus both given as parameters\n            a = aParam;\n            m = mParam;\n        } else if (!aParam && mParam) {\n            // Case 2: value missing - take from input\n            a = inputVal;\n            m = mParam;\n            if (!a) throw new OperationError(\"Value (a) must be defined\");\n        } else if (aParam && !mParam) {\n            // Case 3: modulus missing - take from input\n            a = aParam;\n            m = inputVal;\n            if (!m) throw new OperationError(\"Modulus (m) must be defined\");\n        } else if (!aParam && !mParam) {\n            // Case 4: value and modulus both missing\n            throw new OperationError(\"Value (a) and Modulus (m) must be defined\");\n        }\n\n        const aBI = parseBigInt(a, \"Value (a)\");\n        const mBI = parseBigInt(m, \"Modulus (m)\");\n\n        if (mBI <= 0n) {\n            throw new OperationError(\"Modulus must be greater than zero\");\n        }\n\n        const aNorm = ((aBI % mBI) + mBI) % mBI;\n        const [g, x] = egcd(aNorm, mBI);\n\n        if (g !== 1n && g !== -1n) {\n            throw new OperationError(\"Inverse does not exist because gcd(a, m) ≠ 1\");\n        }","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/ModularInverse.mjs#L59-L95","documentation":"Thrown by Modular Inverse in Case 3: the Modulus (m) argument is blank, so the operation expects to read 'm' from Input, but Input is also empty/whitespace. A modulus is required to define the ring in which the inverse is computed, so the operation aborts.","triggerScenarios":"run(input, args) with args[0] (Value) populated, args[1] (Modulus) empty/whitespace, and input empty/whitespace-only.","commonSituations":"User supplies the value as a parameter but forgets that the modulus must then come from Input; recipe where the modulus stream was renamed or disconnected; whitespace-only input.","solutions":["Provide a Modulus (m) argument, or place the modulus in the Input field when Modulus is blank.","Make sure the Input string contains an actual number, not whitespace.","When scripting, fill exactly one of {Value, Modulus} from Input and the other as an argument."],"exampleFix":"// before: Value set, Modulus empty, Input empty\nchef.bake(\"Modular Inverse\", [\"3\", \"\"], \"\");\n// after: modulus from Input\nchef.bake(\"Modular Inverse\", [\"3\", \"\"], \"7\");","handlingStrategy":"validation","validationCode":"const mParam = (args[1] ?? \"\").trim();\nconst inputVal = (input ?? \"\").trim();\nif (!mParam && !inputVal) {\n  // supply a modulus before calling Modular Inverse\n}","typeGuard":"const hasModulusSource = (mStr, input) =>\n  Boolean((mStr ?? \"\").trim()) || Boolean((input ?? \"\").trim());","tryCatchPattern":"try { chef.bake(\"Modular Inverse\", [a, \"\"], input); }\ncatch (e) { if (e.message.startsWith(\"Modulus (m) must be defined\")) supplyM(); else throw e; }","preventionTips":["Provide Modulus explicitly or guarantee Input holds it.","Validate that at least one modulus source is non-empty.","Remember trim() collapses whitespace to empty."],"tags":["crypto","modular-arithmetic","argument-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}