{"record":{"id":"0d7108b2d2f96a0a","repo":"apache/flink","slug":"unexpected-eof-during-forward-seek","errorCode":null,"errorMessage":"Unexpected EOF during forward seek.","messagePattern":"Unexpected EOF during forward seek\\.","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/io/InputStreamFSInputWrapper.java","lineNumber":58,"sourceCode":"    public InputStreamFSInputWrapper(InputStream inStream) {\n        this.inStream = inStream;\n    }\n\n    @Override\n    public void close() throws IOException {\n        this.inStream.close();\n    }\n\n    @Override\n    public void seek(long desired) throws IOException {\n        if (desired < this.pos) {\n            throw new IllegalArgumentException(\"Wrapped InputStream: cannot search backwards.\");\n        }\n\n        while (this.pos < desired) {\n            long numReadBytes = this.inStream.skip(desired - pos);\n            if (numReadBytes == -1) {\n                throw new EOFException(\"Unexpected EOF during forward seek.\");\n            }\n            this.pos += numReadBytes;\n        }\n    }\n\n    @Override\n    public long getPos() throws IOException {\n        return this.pos;\n    }\n\n    @Override\n    public int read() throws IOException {\n        int read = inStream.read();\n        if (read != -1) {\n            this.pos++;\n        }\n        return read;\n    }","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/io/InputStreamFSInputWrapper.java#L40-L76","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: seek to a length that may exceed real bytes\nlong target = split.getLength();\nwrapper.seek(target);\n// after: clamp to actual available bytes\nlong target = Math.min(split.getLength(), wrapper.getPos() + bytesRemaining);\ntry { wrapper.seek(target); } catch (EOFException e) { /* split exhausted */ }","handlingStrategy":"validation","validationCode":"long len = fs.getFileStatus(path).getLen();\nlong target = Math.min(desired, len);\nif (target < wrapper.getPos()) target = wrapper.getPos();\ntry {\n    wrapper.seek(target);\n} catch (EOFException e) {\n    // treat as exhausted\n}","typeGuard":"static long clampedSeekTarget(long desired, long current, long length) {\n    if (desired < current) throw new IllegalArgumentException(\"backward seek\");\n    return Math.min(desired, length);\n}","tryCatchPattern":"try {\n    wrapper.seek(desired);\n} catch (EOFException e) {\n    // split is shorter than expected; stop reading this split\n    LOG.warn(\"EOF seeking to {} in {}\", desired, path);\n    return Record.EOF;\n}","preventionTips":["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."],"tags":["io","input-stream","eof","filesystem"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}