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
- Re-stat the source to get the current length and clamp seek targets to [pos, length].
- Handle EOFException by treating the split as exhausted rather than fatal, if the reader supports partial data.
- For compressed/indeterminate-length streams, prefer length-agnostic reading (read until EOF) rather than computing offsets.
- 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
- Re-stat the source for the current length before computing seek targets; clamp to it.
- Handle EOFException as 'split exhausted' rather than fatal for streaming/indeterminate sources.
- Avoid computing offsets from compressed lengths; read length-agnostic when possible.
- Ensure the file is fully written and not concurrently modified before splitting.
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
- Wrapped InputStream: cannot search backwards.
- An I/O error occurred while creating temporary file to extra
- Failed to create parent(s) for given base dir: %s
- Compaction file not exist: {path}
- An error occurred while copying the file.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/0d7108b2d2f96a0a.
Report an issue: GitHub.