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

  1. Clamp or validate len >= 0 before calling read; treat negative as zero or an error in your code
  2. Check for int/long overflow when converting unsigned metadata sizes to signed Java types
  3. Fix computation order so the read length is end - start with start <= end
  4. 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

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


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)