{"record":{"id":"f2b37c67412de20c","repo":"apache/flink","slug":"wrapped-inputstream-cannot-search-backwards","errorCode":null,"errorMessage":"Wrapped InputStream: cannot search backwards.","messagePattern":"Wrapped InputStream: cannot search backwards\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/io/InputStreamFSInputWrapper.java","lineNumber":52,"sourceCode":"public class InputStreamFSInputWrapper extends FSDataInputStream {\n\n    private final InputStream inStream;\n\n    private long pos = 0;\n\n    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 {","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/io/InputStreamFSInputWrapper.java#L34-L70","documentation":"Thrown by InputStreamFSInputWrapper.seek(desired) when desired < current position. The wrapper adapts a plain forward-only java.io.InputStream to Flink's seekable FSInputStream interface, but can only skip forward (via InputStream.skip). Backward seeks are impossible without re-opening the stream, so they are rejected.","triggerScenarios":"Code treats an InputStreamFSInputWrapper as a random-access FSDataInputStream and calls seek to a position earlier than getPos(). Common when a reader needs to rewind (e.g. to re-read a block, retry a record, or seek to a checkpoint) but the underlying source is a socket/stream rather than a file.","commonSituations":"Wrapping a non-seekable source (HTTP stream, socket, pipe) and passing it to code that assumes file-like random access; checkpoint/restart logic that seeks backward; format readers that re-read headers; tests using a ByteArrayInputStream wrapper that expect full seeking.","solutions":["Use a true FSDataInputStream backed by a seekable file (e.g. via a FileSystem that supports random access) instead of InputStreamFSInputWrapper for any code that may seek backward.","If you only ever need forward seeks, ensure all seek targets are >= the current position.","Buffer the stream into a byte array / temp file and wrap that for full random access when backward seeks are required."],"exampleFix":"// before: backward seek throws\nFSDataInputStream in = new InputStreamFSInputWrapper(socketStream);\nin.seek(in.getPos() - 10);\n// after: buffer to a seekable file first\nPath tmp = bufferToTempFile(socketStream);\nFSDataInputStream in = fs.open(tmp);\nin.seek(in.getPos() - 10);","handlingStrategy":"validation","validationCode":"if (desired < wrapper.getPos()) {\n    throw new IllegalStateException(\n        \"Cannot seek backward on InputStreamFSInputWrapper: desired=\" + desired\n        + \" pos=\" + wrapper.getPos());\n}\nwrapper.seek(desired);","typeGuard":"// Use a capability flag to pick the right stream type\nboolean needsBackwardSeek = ...;\nFSDataInputStream in = needsBackwardSeek\n    ? openSeekableFile(fs, path)              // true random access\n    : new InputStreamFSInputWrapper(stream);  // forward-only","tryCatchPattern":"try {\n    wrapper.seek(desired);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"cannot search backwards\")) {\n        // re-open the underlying stream from the start, then skip forward\n        reopenAndSkipTo(desired);\n        return;\n    }\n    throw e;\n}","preventionTips":["Only use InputStreamFSInputWrapper when you are certain seeks are monotonic forward.","For random access, open the file through a FileSystem that returns a seekable FSDataInputStream.","If backward seeks may occur, buffer the stream to a temp file first and wrap that."],"tags":["io","input-stream","seek","filesystem"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}