{"id":"cdfefff7d9c6c0dc","repo":"apache/kafka","slug":"invalid-size-in-read-from","errorCode":null,"errorMessage":"Invalid size: {} in read from {}","messagePattern":"Invalid size: (.+?) in read from (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/record/internal/FileRecords.java","lineNumber":177,"sourceCode":"     * @return A unaligned slice of records on this message set limited based on the given position and size\n     */\n    public UnalignedFileRecords sliceUnaligned(int position, int size) {\n        int availableBytes = availableBytes(position, size);\n        return new UnalignedFileRecords(channel, this.start + position, availableBytes);\n    }\n\n    private int availableBytes(int position, int size) {\n        // Cache current size in case concurrent write changes it\n        int currentSizeInBytes = sizeInBytes();\n\n        if (position < 0)\n            throw new IllegalArgumentException(\"Invalid position: \" + position + \" in read from \" + this);\n        // position should always be relative to the start of the file hence compare with file size\n        // to verify if the position is within the file.\n        if (position > currentSizeInBytes)\n            throw new IllegalArgumentException(\"Slice from position \" + position + \" exceeds end position of \" + this);\n        if (size < 0)\n            throw new IllegalArgumentException(\"Invalid size: \" + size + \" in read from \" + this);\n\n        int end = this.start + position + size;\n        // Handle integer overflow or if end is beyond the end of the file\n        if (end < 0 || end > start + currentSizeInBytes)\n            end = this.start + currentSizeInBytes;\n        return end - (this.start + position);\n    }\n\n    /**\n     * Append a set of records to the file. This method is not thread-safe and must be\n     * protected with a lock.\n     *\n     * @param records The records to append\n     * @return the number of bytes written to the underlying file\n     */\n    public int append(MemoryRecords records) throws IOException {\n        if (records.sizeInBytes() > Integer.MAX_VALUE - size.get())\n            throw new IllegalArgumentException(\"Append of size \" + records.sizeInBytes() +","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/record/internal/FileRecords.java#L159-L195","documentation":"Thrown by FileRecords.availableBytes when the requested size argument is negative. A negative read length is undefined for FileChannel transfers, so the guard rejects it before computing the end offset. Like the position check, this is a programmer-error guard against malformed slice/sliceUnaligned calls.","triggerScenarios":"Calling FileRecords.slice(position, size) or sliceUnaligned(position, size) with a negative size. Reachable from fetch/replication code paths that compute the read length from an offset difference or from min(fetchSize, ...) expressions.","commonSituations":"Subtracting a larger number from a smaller one (e.g. endOffset - startOffset when the start is past the end), an off-by-one in fetch min/max math, or a misconfigured fetch.min.bytes/fetch.max.bytes. Rare in production code paths; more common in tests and custom consumers.","solutions":["Trace the caller of slice/sliceUnaligned and confirm the size argument is derived from a non-negative length, not a signed difference.","Bound the size at the source: use Math.max(0, end - start) before passing it in.","Check fetch-size config (max.partition.fetch.bytes, fetch.max.bytes) for negative or absurd values."],"exampleFix":"// before: size can go negative when end < start\nint size = endOffset - startOffset;\nreturn records.slice(position, size);\n\n// after: clamp size so negative deltas become zero-length reads\nint size = Math.max(0, endOffset - startOffset);\nreturn records.slice(position, size);","handlingStrategy":"validation","validationCode":"if (size < 0) {\n    throw new IllegalArgumentException(\n        \"read/slice size must be >= 0, got \" + size);\n}\nFileRecords slice = records.slice(position, size);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp requested sizes to Math.max(0, size) at the call boundary.","Beware arithmetic underflow (e.g. endOffset - startOffset) that can go negative on bad input.","Treat negative sizes as a programming error, not a retryable condition."],"tags":["file-records","slice","validation","argument-error"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}