apache/iceberg · error · IndexOutOfBoundsException
Read length must be greater than 0
Error message
Read length must be greater than 0: <len>
What it means
MultiBufferInputStream.read(byte[], off, len) throws IndexOutOfBoundsException when len is negative, since a negative read length is meaningless. This follows the InputStream contract; len == 0 legally returns 0 without reading. The message reports the offending len value.
Solutions
- Clamp or validate len >= 0 before calling read; treat negative as zero or an error in your code
- Check for int/long overflow when converting unsigned metadata sizes to signed Java types
- Fix computation order so the read length is end - start with start <= end
- Catch IndexOutOfBoundsException at the reader boundary and surface which length was computed
Example fix
// before
int len = (int) (endPos - startPos); // may be negative or overflow
stream.read(buf, 0, len);
// after
int len = (int) Math.max(0, endPos - startPos);
if (len > 0) {
stream.read(buf, 0, len);
} Defensive patterns
Strategy: validation
Validate before calling
if (len < 0) {
throw new IllegalArgumentException("Negative read length " + len + " (likely unsigned overflow)");
}
stream.read(buf, off, len); Type guard
int safeLen(long computedLen) {
return (int) Math.min(Math.max(computedLen, 0L), Integer.MAX_VALUE);
} Try / catch
try {
stream.read(buf, off, len);
} catch (IndexOutOfBoundsException e) {
throw new IOException("Bad read length; check unsigned size handling", e);
} Prevention
- Clamp computed lengths to >= 0 before reading
- Use unsigned-safe conversions for metadata sizes read into signed ints
- Ensure position differences are taken in the correct order
When it happens
Trigger: Calling read(buf, off, len) with len < 0 — usually from an unsigned-to-signed arithmetic bug (e.g. an int/long overflow making a size negative) or passing a negative remaining count computed as len = end - start with start > end.
Common situations: Reading sizes from metadata stored as unsigned ints but read into signed ints (large values wrap negative); computing read length as a difference of positions that are out of order; off-by-one loops passing negative remainders.
Related errors
- AboveMax has no value
- An error occurred while aborting the stream
- An error occurred while closing the stream
- Bulk deletion failed
- Can't create file
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0d028a92b28f3fe4.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/io/MultiBufferInputStream.java:233
@Override
public List<ByteBuffer> remainingBuffers() {
if (position >= length) {
return Collections.emptyList();
}
try {
return sliceBuffers(length - position);
} catch (EOFException e) {
throw new RuntimeException(
"[Parquet bug] Stream is bad: incorrect bytes remaining " + (length - position));
}
}
@Override
public int read(byte[] bytes, int off, int len) {
if (len <= 0) {
if (len < 0) {
throw new IndexOutOfBoundsException("Read length must be greater than 0: " + len);
}
return 0;
}
if (current == null) {
return -1;
}
int bytesRead = 0;
while (bytesRead < len) {
if (current.remaining() > 0) {
int bytesToRead = Math.min(len - bytesRead, current.remaining());
current.get(bytes, off + bytesRead, bytesToRead);
bytesRead += bytesToRead;
this.position += bytesToRead;
} else if (!nextBuffer()) {
// there are no more buffers
return bytesRead > 0 ? bytesRead : -1;View on GitHub (pinned to 86d9c8fc54)