{"record":{"id":"66a727745befe9b4","repo":"gchq/CyberChef","slug":"blocksize-must-be-a-positive-integer","errorCode":null,"errorMessage":"Blocksize must be a positive integer.","messagePattern":"Blocksize must be a positive integer\\.","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/XORChecksum.mjs","lineNumber":48,"sourceCode":"            {\n                name: \"Blocksize\",\n                type: \"number\",\n                value: 4,\n            },\n        ];\n    }\n\n    /**\n     * @param {ArrayBuffer} input\n     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        const blocksize = args[0];\n\n\n        if (!Number.isInteger(blocksize) || blocksize <= 0) {\n            throw new OperationError(\"Blocksize must be a positive integer.\");\n        }\n\n        input = new Uint8Array(input);\n\n        const res = Array(blocksize);\n        res.fill(0);\n\n        for (const chunk of Utils.chunked(input, blocksize)) {\n            for (let i = 0; i < blocksize; i++) {\n                res[i] ^= chunk[i];\n            }\n        }\n\n        return toHex(res, \"\");\n    }\n}\n\nexport default XORChecksum;","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/XORChecksum.mjs#L30-L66","documentation":"Thrown by XORChecksum.run when validating args[0] ('Blocksize'). The checksum XORs fixed-size blocks, so the size must be a positive integer; Number.isInteger(x) && x > 0 guards both fractional values and non-positive ones. The default is 4 (declared in the constructor), so a valid UI invocation never hits this — it only fires when a number argument is supplied out of range.","triggerScenarios":"Blocksize is supplied as 0, a negative number, NaN/Infinity, a fractional value (e.g. 2.5), or is missing/corrupted in a programmatic opList. Strings are not integers, so passing '4' as a JSON string also fails Number.isInteger.","commonSituations":"Hand-built recipe JSON where the number was serialised as a string; a UI/config preset copied with blocksize 0; off-by-one when deriving blocksize from input length.","solutions":["Pass a positive integer (>=1) for the Blocksize argument, e.g. 1, 2, 4, 8.","Ensure the value is a real number, not a JSON string: '4' fails; 4 passes.","If computing blocksize dynamically, clamp with Math.max(1, Math.floor(n)) and confirm it is an integer before building the recipe."],"exampleFix":"// before\nchef.bake(input, [{op:\"XOR Checksum\", args:[\"4\"]}]); // string -> not an integer\nchef.bake(input, [{op:\"XOR Checksum\", args:[0]}]);   // not positive\n// after\nchef.bake(input, [{op:\"XOR Checksum\", args:[4]}]);","handlingStrategy":"validation","validationCode":"function buildXorRecipe(blocksize) {\n  if (!Number.isInteger(blocksize) || blocksize <= 0) throw new Error(\"blocksize must be a positive integer\");\n  return [{op:\"XOR Checksum\", args:[blocksize]}];\n}","typeGuard":"const isPositiveInt = (n) => Number.isInteger(n) && n > 0;","tryCatchPattern":"try { result = chef.bake(input, recipe); } catch (e) { if (/Blocksize must be a positive integer/.test(e.message)) { /* coerce: recipe[0].args[0] = Math.max(1, Math.floor(x)) */ } else throw e; }","preventionTips":["Pass numbers, not strings, for numeric args in JSON.","Clamp dynamic blocksize with Math.max(1, Math.floor(n)).","Unit-test recipe builders with 0, 1, fractional, and negative inputs."],"tags":["xor-checksum","operation-args","numeric-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}