{"record":{"id":"dbaf6be3f7a2fdf4","repo":"LMAX-Exchange/disruptor","slug":"a-batchsize-of-with-batchstatsat-of-will-o","errorCode":null,"errorMessage":"A batchSize of: {} with batchStatsAt of: {} will overrun the available number of arguments: {}","messagePattern":"A batchSize of: (.+?) with batchStatsAt of: (.+?) will overrun the available number of arguments: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/lmax/disruptor/RingBuffer.java","lineNumber":944,"sourceCode":"        final A[] arg0, final B[] arg1, final C[] arg2, final int batchStartsAt, final int batchSize)\n    {\n        checkBatchSizing(batchStartsAt, batchSize);\n        batchOverRuns(arg0, batchStartsAt, batchSize);\n        batchOverRuns(arg1, batchStartsAt, batchSize);\n        batchOverRuns(arg2, batchStartsAt, batchSize);\n    }\n\n    private void checkBounds(final int batchStartsAt, final int batchSize, final Object[][] args)\n    {\n        checkBatchSizing(batchStartsAt, batchSize);\n        batchOverRuns(args, batchStartsAt, batchSize);\n    }\n\n    private <A> void batchOverRuns(final A[] arg0, final int batchStartsAt, final int batchSize)\n    {\n        if (batchStartsAt + batchSize > arg0.length)\n        {\n            throw new IllegalArgumentException(\n                \"A batchSize of: \" + batchSize +\n                    \" with batchStatsAt of: \" + batchStartsAt +\n                    \" will overrun the available number of arguments: \" + (arg0.length - batchStartsAt));\n        }\n    }\n\n    private void translateAndPublish(final EventTranslator<E> translator, final long sequence)\n    {\n        try\n        {\n            translator.translateTo(get(sequence), sequence);\n        }\n        finally\n        {\n            sequencer.publish(sequence);\n        }\n    }\n","sourceCodeStart":926,"sourceCodeEnd":962,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/main/java/com/lmax/disruptor/RingBuffer.java#L926-L962","documentation":"Thrown by RingBuffer.batchOverRuns during batch publishing when batchStartsAt + batchSize walks past the end of the supplied argument array. The message reports how many arguments actually remain from batchStartsAt; publishing would otherwise read beyond the array and copy garbage (or throw ArrayIndexOutOfBoundsException deep inside the ring).","triggerScenarios":"Calling publishEvents(translators, 8, 4) when translators.length == 10 (8 + 4 = 12 > 10); any variant (tryPublishEvents, publishEvents with arg arrays, varargs) where offset plus count exceeds the source array length.","commonSituations":"Chunking loop with an incorrect tail calculation (forgetting Math.min for the last chunk); reusing an offset from a previous larger batch; off-by-one where count includes an element outside the array.","solutions":["Clamp the count to the remaining elements: n = Math.min(chunk, args.length - start).","Double-check that batchStartsAt is an index into the SAME array being published.","Write a boundary unit test for the final partial chunk."],"exampleFix":"// before\nint count = batchSize; // last chunk overruns the array\nringBuffer.publishEvents(translators, start, count);\n\n// after\nint count = Math.min(batchSize, translators.length - start);\nringBuffer.publishEvents(translators, start, count);","handlingStrategy":"validation","validationCode":"int count = Math.min(batchSize, args.length - batchStartsAt);\nif (batchStartsAt + count > args.length) throw new IllegalArgumentException(\"batch overruns args\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always clamp the last chunk with Math.min(chunk, remaining).","Add a boundary unit test for the final partial chunk of every batch loop."],"tags":["disruptor","ring-buffer","batching","off-by-one","publish"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}