{"record":{"id":"1d34f3ba6c3cdaca","repo":"gchq/CyberChef","slug":"modulus-must-be-defined","errorCode":null,"errorMessage":"Modulus must be defined","messagePattern":"Modulus must be defined","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/ModularExponentiation.mjs","lineNumber":68,"sourceCode":"    }\n\n    /**\n      * @param {string} input\n      * @param {Object[]} args\n      * @returns {string}\n      */\n    run(input, args) {\n        const [baseStr, modStr, expStr] = args;\n\n        // Trim everything so \"\" and \"   \" count as empty\n        const baseParam = baseStr?.trim();\n        const expParam  = expStr?.trim();\n        const modParam  = modStr?.trim();\n        const inputVal  = input?.trim();\n\n        const mod = modParam;\n        if (!mod) {\n            throw new OperationError(\"Modulus must be defined\");\n        }\n\n        // Base *or* Exponent (but not both) are taken from the Input\n        // if their boxes are empty.\n        let base, exp;\n        if (baseParam && expParam) {\n            // Case 1: base and exponent both given as parameters\n            base = baseParam;\n            exp  = expParam;\n        } else if (!baseParam && expParam) {\n            // Case 2: base missing - take from input\n            base = inputVal;\n            exp  = expParam;\n            if (!base) {\n                throw new OperationError(\"Base must be defined\");\n            }\n        } else if (baseParam && !expParam) {\n            // Case 3: exponent missing - take from input","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/ModularExponentiation.mjs#L50-L86","documentation":"Thrown by the Modular Exponentiation operation when the 'Modulus' argument (args[1]) is empty or whitespace-only. run() trims modStr and rejects a falsy result at ModularExponentiation.mjs:68 before base/exponent resolution. The default modulus is '1', so this only fires when the field is explicitly cleared or set to blanks.","triggerScenarios":"Invoking Modular Exponentiation with args[1] ('Modulus') set to '', '   ', or omitted. Raised at ModularExponentiation.mjs:67-69. A later check (line 103) separately rejects a modulus that parses to 0.","commonSituations":"User cleared the Modulus field expecting it to be optional; a recipe JSON with a missing/blank modulus; copy/paste that left only whitespace.","solutions":["Provide a non-empty, positive integer Modulus (e.g. the default '1', or your RSA/DH modulus).","When building recipes programmatically, default modulus to '1' if blank.","Validate modStr.trim() is non-empty before running."],"exampleFix":"// before\nmodExp.run('', ['', '', '']);   // modulus blank -> throws\n\n// after\nmodExp.run('2', ['', '15', '']);  // modulus 15 -> computes 2^input mod 15","handlingStrategy":"validation","validationCode":"function definedModulus(m) {\n  const v = String(m ?? '').trim();\n  if (!v) throw new Error('Modulus must be defined');\n  return v;\n}\nconst mod = definedModulus(args[1]);","typeGuard":"function isDefinedModulus(v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Keep the default modulus ('1') unless you intentionally change it.","Treat a blank/whitespace modulus as invalid at recipe build time.","Remember a later check also rejects modulus == 0 after parsing."],"tags":["modular-exponentiation","crypto","rsa","validation","argument-required"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}