apache/iceberg · error · EOFException
Cannot read bytes at position : exceeds stream length…
Error message
Cannot read <length> bytes at position <pos>: exceeds stream length <contents.length>
What it means
EagerInputStream.readFully throws EOFException when the requested [pos, pos+length) window lies beyond the in-memory contents array. It is a bounds check that prevents partial reads from the fixed-size byte buffer backing the eager stream.
Solutions
- Clamp or validate pos and length against the file length before reading.
- Refresh the eager contents — the buffer may be stale or truncated (see the incorrect-length error).
- Fix the offset/length source (footer metadata) if it points outside the file.
- Use the stream's length() to size reads dynamically.
Example fix
// before
stream.readFully(pos, buf, 0, buf.length);
// after
long len = stream.getLength();
long readable = Math.min(buf.length, len - pos);
if (readable <= 0) throw new IllegalArgumentException("pos " + pos + " beyond end of stream");
stream.readFully(pos, buf, 0, (int) readable); Defensive patterns
Strategy: validation
Validate before calling
long fileLen = stream.getLength();
if (pos < 0 || pos > fileLen || length > fileLen - pos) {
throw new IllegalArgumentException("Read window out of bounds");
} Try / catch
try {
stream.readFully(pos, buf, offset, length);
} catch (EOFException e) {
LOG.error("Read [{}..{}] beyond length {}", pos, pos + length, contentsLength);
throw e;
} Prevention
- Compute lengths from the stream's own getLength(), not assumptions
- Validate footer-derived ranges before reading
- Refresh eager contents if the buffer may be stale/truncated
- Prefer the positional readFully over seek+read loops for bulk reads
When it happens
Trigger: Calling readFully(pos, buffer, offset, length) where pos > contents.length or pos + length > contents.length on a stream from EagerInputFile.newStream().
Common situations: Footer parsers requesting ranges beyond a truncated/stale buffer; using offsets from metadata that referenced a larger file; off-by-one or wrong length computations in read loops.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Cannot seek to position
- Cannot read manifest list file
- Failed to close manifest reader
- Failed to read manifest
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/acaac2805224ca9e.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/io/EagerInputStream.java:78
return delegate.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return delegate.skip(n);
}
@Override
public int available() throws IOException {
return delegate.available();
}
@Override
public void readFully(long pos, byte[] buffer, int offset, int length) throws IOException {
Preconditions.checkPositionIndexes(offset, offset + length, buffer.length);
Preconditions.checkArgument(pos >= 0, "position is negative: %s", pos);
if (pos > contents.length || length > contents.length - pos) {
throw new EOFException(
"Cannot read "
+ length
+ " bytes at position "
+ pos
+ ": exceeds stream length "
+ contents.length);
}
System.arraycopy(contents, (int) pos, buffer, offset, length);
}
@Override
public int readTail(byte[] buffer, int offset, int length) throws IOException {
Preconditions.checkPositionIndexes(offset, offset + length, buffer.length);
int bytesToCopy = Math.min(length, contents.length);
System.arraycopy(contents, contents.length - bytesToCopy, buffer, offset, bytesToCopy);
return bytesToCopy;
}
View on GitHub (pinned to 86d9c8fc54)