apache/flink · error · EOFException

Unexpected EOF during forward seek.

Error message

Unexpected EOF during forward seek.

What it means

Thrown by InputStreamFSInputWrapper.seek during a forward skip when InputStream.skip returns -1, indicating the stream ended before the desired position was reached. This is an EOFException signalling the seek target is past the end of the available data.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/io/InputStreamFSInputWrapper.java:58

    public InputStreamFSInputWrapper(InputStream inStream) {
        this.inStream = inStream;
    }

    @Override
    public void close() throws IOException {
        this.inStream.close();
    }

    @Override
    public void seek(long desired) throws IOException {
        if (desired < this.pos) {
            throw new IllegalArgumentException("Wrapped InputStream: cannot search backwards.");
        }

        while (this.pos < desired) {
            long numReadBytes = this.inStream.skip(desired - pos);
            if (numReadBytes == -1) {
                throw new EOFException("Unexpected EOF during forward seek.");
            }
            this.pos += numReadBytes;
        }
    }

    @Override
    public long getPos() throws IOException {
        return this.pos;
    }

    @Override
    public int read() throws IOException {
        int read = inStream.read();
        if (read != -1) {
            this.pos++;
        }
        return read;
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Re-stat the source to get the current length and clamp seek targets to [pos, length].
  2. Handle EOFException by treating the split as exhausted rather than fatal, if the reader supports partial data.
  3. For compressed/indeterminate-length streams, prefer length-agnostic reading (read until EOF) rather than computing offsets.
  4. Ensure the file is fully written / not concurrently modified before computing splits.

Example fix

// before: seek to a length that may exceed real bytes
long target = split.getLength();
wrapper.seek(target);
// after: clamp to actual available bytes
long target = Math.min(split.getLength(), wrapper.getPos() + bytesRemaining);
try { wrapper.seek(target); } catch (EOFException e) { /* split exhausted */ }
Defensive patterns

Strategy: validation

Validate before calling

long len = fs.getFileStatus(path).getLen();
long target = Math.min(desired, len);
if (target < wrapper.getPos()) target = wrapper.getPos();
try {
    wrapper.seek(target);
} catch (EOFException e) {
    // treat as exhausted
}

Type guard

static long clampedSeekTarget(long desired, long current, long length) {
    if (desired < current) throw new IllegalArgumentException("backward seek");
    return Math.min(desired, length);
}

Try / catch

try {
    wrapper.seek(desired);
} catch (EOFException e) {
    // split is shorter than expected; stop reading this split
    LOG.warn("EOF seeking to {} in {}", desired, path);
    return Record.EOF;
}

Prevention

When it happens

Trigger: A caller seeks to a position beyond the actual length of the wrapped stream, e.g. a split length or offset that exceeds the real byte count, or a stale file size used to compute the seek target.

Common situations: File truncated/rotated between size discovery and read; split length computed from outdated file stats; compressed stream whose uncompressed length differs from the compressed length used for seeking; reading past a partial download; race with a writer still appending.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/0d7108b2d2f96a0a. Report an issue: GitHub.