apache/iceberg · error · EOFException

Cannot seek to position after end of file

Error message

Cannot seek to position after end of file: %s

What it means

MultiBufferInputStream backs a single stream view over a list of ByteBuffers and tracks the logical file length. seek(newPosition) beyond that length throws EOFException because the stream has no data there. It is a guard against reads past the logical end of the wrapped buffers.

Solutions

  1. Validate the target position against the stream length before seeking (position <= length)
  2. Load the correct/full buffer range that contains the offset being seeked to
  3. If slicing a file, seek with offsets relative to the slice, not the original file
  4. Refresh metadata offsets if the file was rewritten
  5. Catch EOFException and surface a clear 'offset beyond data' error to the caller

Example fix

// before
stream.seek(footerOffset); // EOFException when footerOffset > loaded buffers
// after
if (footerOffset > stream.getLength()) {
  throw new IOException("Offset beyond stream end: " + footerOffset);
}
stream.seek(footerOffset);
Defensive patterns

Strategy: validation

Validate before calling

if (newPosition > stream.getLength()) {
  throw new IOException("Seek position " + newPosition + " beyond stream length " + stream.getLength());
}
stream.seek(newPosition);

Try / catch

try {
  stream.seek(pos);
} catch (EOFException e) {
  throw new IOException("Seek beyond end of loaded data at " + pos, e);
}

Prevention

When it happens

Trigger: Calling seek(long) on a MultiBufferInputStream with a position greater than the total length of the supplied buffers — typically a metadata-driven seek (footer offset, row-group offset) that exceeds the data actually loaded, or passing a stale/incorrect offset.

Common situations: Parquet column readers seeking to a row-group offset from metadata that doesn't match the buffer slice loaded; loading only a partial file range (e.g. a split) but seeking with absolute file offsets; corrupted/stale footer offsets.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/e0a45d2dddca18cc. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/io/MultiBufferInputStream.java:72

    initFromBuffers();
  }

  private void initFromBuffers() {
    discardMark();
    this.position = 0;
    this.iterator = buffers.stream().map(ByteBuffer::duplicate).iterator();
    nextBuffer();
  }

  @Override
  public long getPos() {
    return position;
  }

  @Override
  public void seek(long newPosition) throws IOException {
    if (newPosition > length) {
      throw new EOFException(
          String.format("Cannot seek to position after end of file: %s", newPosition));
    }

    if (position > newPosition) {
      // backward seek requires returning to the initial state
      initFromBuffers();
    }

    long bytesToSkip = newPosition - position;
    skipFully(bytesToSkip);
  }

  @Override
  public long skip(long n) {
    if (n <= 0) {
      return 0;
    }

View on GitHub (pinned to 86d9c8fc54)