{"record":{"id":"fa635d3f2be35d85","repo":"gchq/CyberChef","slug":"offset-has-to-be-a-positive-integer-fa635d","errorCode":null,"errorMessage":"Offset has to be a positive integer","messagePattern":"Offset has to be a positive integer","errorType":"validation","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/RailFenceCipherEncode.mjs","lineNumber":57,"sourceCode":"    }\n\n    /**\n     * @param {string} input\n     * @param {Object[]} args\n     * @returns {string}\n     */\n    run(input, args) {\n        const [key, offset] = args;\n\n        const plaintext = input;\n        if (key < 2) {\n            throw new OperationError(\"Key has to be bigger than 2\");\n        } else if (key > plaintext.length) {\n            throw new OperationError(\"Key should be smaller than the plain text's length\");\n        }\n\n        if (offset < 0) {\n            throw new OperationError(\"Offset has to be a positive integer\");\n        }\n\n        const cycle = (key - 1) * 2;\n        const rows = new Array(key).fill(\"\");\n\n        for (let pos = 0; pos < plaintext.length; pos++) {\n            const rowIdx = key - 1 - Math.abs(cycle / 2 - (pos + offset) % cycle);\n\n            rows[rowIdx] += plaintext[pos];\n        }\n\n        return rows.join(\"\");\n    }\n\n}\n\nexport default RailFenceCipherEncode;\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/RailFenceCipherEncode.mjs#L39-L75","documentation":"Thrown by RailFenceCipherEncode when the 'offset' argument is negative. Offset must be a non-negative integer because it shifts the zigzag starting position.","triggerScenarios":"Negative offset value; recipe/config supplying a negative number.","commonSituations":"Sign typo; mismatched offset between encode/decode; imported recipe with bad default.","solutions":["Set offset to 0 or a positive integer.","Use the same offset used when decoding.","Clamp with Math.max(0, offset)."],"exampleFix":"// before\n//   offset: -1\n// after\n//   offset: 0","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(offset) || offset < 0) throw new Error('Offset must be a non-negative integer');","typeGuard":"const isOffset = o => Number.isInteger(o) && o >= 0;","tryCatchPattern":"try { encode(input, { offset }); } catch (e) { if (/Offset/.test(e.message)) offset = 0; else throw e; }","preventionTips":["Clamp offset to >= 0.","Match encode/decode offsets."],"tags":["cipher","rail-fence","validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}