{"record":{"id":"aff7865a80f167a3","repo":"MyCATApache/Mycat-Server","slug":"both-batchstartsat-and-batchsize-must-be-positive","errorCode":null,"errorMessage":"Both batchStartsAt and batchSize must be positive but got: batchStartsAt ${batchStartsAt} and batchSize ${batchSize}","messagePattern":"Both batchStartsAt and batchSize must be positive but got: batchStartsAt (.+?) and batchSize (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/memory/unsafe/ringbuffer/RingBuffer.java","lineNumber":279,"sourceCode":"    }\n\n    private void checkBounds(final EventTranslator<E>[] translators, final int batchStartsAt, final int batchSize) {\n        checkBatchSizing(batchStartsAt, batchSize);\n        batchOverRuns(translators, batchStartsAt, batchSize);\n    }\n\n    private <A> void batchOverRuns(final A[] arg0, final int batchStartsAt, final int batchSize) {\n        if (batchStartsAt + batchSize > arg0.length) {\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 checkBatchSizing(int batchStartsAt, int batchSize) {\n        if (batchStartsAt < 0 || batchSize < 0) {\n            throw new IllegalArgumentException(\"Both batchStartsAt and batchSize must be positive but got: batchStartsAt \" + batchStartsAt + \" and batchSize \" + batchSize);\n        } else if (batchSize > bufferSize) {\n            throw new IllegalArgumentException(\"The ring buffer cannot accommodate \" + batchSize + \" it only has space for \" + bufferSize + \" entities.\");\n        }\n    }\n\n    /**\n     * @see io.mycat.memory.unsafe.ringbuffer.common.event.EventSink#publishEvent(EventTranslator)\n     */\n    @Override\n    public void publishEvents(EventTranslator<E>[] translators) {\n        publishEvents(translators, 0, translators.length);\n    }\n\n    private void translateAndPublishBatch(\n            final EventTranslator<E>[] translators, int batchStartsAt,\n            final int batchSize, final long finalSequence) {\n        final long initialSequence = finalSequence - (batchSize - 1);\n        try {","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/memory/unsafe/ringbuffer/RingBuffer.java#L261-L297","documentation":"checkBatchSizing rejects negative batchStartsAt or batchSize values. Despite the message saying 'positive', the code only rejects values below 0; a negative offset or size would corrupt index arithmetic, so the constructor-style guard throws IllegalArgumentException immediately.","triggerScenarios":"Calling batch publish APIs like publishEvents(translators, batchStartsAt, batchSize) or tryPublishEvents with a negative offset or negative computed size (e.g. batchStartsAt = -1, or batchSize = toIndex - fromIndex where fromIndex > toIndex).","commonSituations":"Reversed range variables (fromIndex > toIndex yielding a negative size), integer subtraction bugs, or unvalidated external input feeding the offset/size parameters.","solutions":["Clamp both parameters with Math.max(0, value) before calling.","Fix the range computation so batchSize = end - start is non-negative (swap or validate start/end).","Validate externally supplied indices/sizes before passing them to the ring buffer.","Use the single-argument publishEvents(translators) overload when the whole array is intended."],"exampleFix":"// before\nint size = end - start; // end < start -> negative\nring.publishEvents(translators, start, size);\n// after\nint from = Math.min(start, end), to = Math.max(start, end);\nring.publishEvents(translators, from, to - from);","handlingStrategy":"validation","validationCode":"public static int safeSize(int start, int end) {\n    if (start < 0 || end < start) return 0;\n    return end - start;\n}\n// pass Math.max(0, batchStartsAt) and safeSize(from, to)","typeGuard":null,"tryCatchPattern":"try {\n    ring.publishEvents(translators, start, size);\n} catch (IllegalArgumentException e) {\n    // negative offset/size: normalize and retry or skip\n    ring.publishEvents(translators, Math.max(0, start), Math.max(0, size));\n}","preventionTips":["Compute batchSize as end - start only after checking start <= end","Never pass raw user input as offset/size without clamping","Assert non-negative start/size in debug builds"],"tags":["java","ringbuffer","batch","illegal-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}