{"record":{"id":"647f96db2ab3400b","repo":"apache/hadoop","slug":"cannot-seek-after-eof","errorCode":null,"errorMessage":"Cannot seek after EOF","messagePattern":"Cannot seek after EOF","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ChecksumFileSystem.java","lineNumber":612,"sourceCode":"      return super.skip(n);\n    }\n\n    /**\n     * Seek to the given position in the stream.\n     * The next read() will be from that position.\n     *\n     * <p>This method does not allow seek past the end of the file.\n     * This produces IOException.\n     *\n     * @param      pos   the postion to seek to.\n     * @exception  IOException  if an I/O error occurs or seeks after EOF\n     *             ChecksumException if the chunk to seek to is corrupted\n     */\n\n    @Override\n    public synchronized void seek(long pos) throws IOException {\n      if (pos > getFileLength()) {\n        throw new EOFException(\"Cannot seek after EOF\");\n      }\n      super.seek(pos);\n    }\n\n  }\n\n  /**\n   * Opens an FSDataInputStream at the indicated Path.\n   * @param f the file name to open\n   * @param bufferSize the size of the buffer to be used.\n   * @throws IOException if an I/O error occurs.\n   */\n  @Override\n  public FSDataInputStream open(Path f, int bufferSize) throws IOException {\n    FileSystem fs;\n    InputStream in;\n    if (verifyChecksum) {\n      fs = this;","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ChecksumFileSystem.java#L594-L630","documentation":"ChecksumFSInputChecker.seek enforces the documented contract \"no seek past the end of the file\": it compares the target against getFileLength() (the cached content-summary length of the file under the ChecksumFileSystem) and throws EOFException(\"Cannot seek after EOF\") when pos exceeds it. This mirrors plain RandomAccessFile semantics - on this class, seeking to or past the effective EOF is an error rather than a no-op.","triggerScenarios":"Seeking to split end + 1, or to a length captured earlier, after the file shrank between listing and read; computing seek targets as getPos()+remaining where the sum overshoots the file; generic seek-based parsers that seek to a footer offset stored in a header that is larger than the current file.","commonSituations":"Input splits computed from a stale FileStatus after the file was rewritten/truncated; concurrent writers replacing local staging files while a reader opens them; off-by-one at exactly EOF (pos == length is allowed, pos > length throws).","solutions":["Clamp the seek target to the current file length: seek(Math.min(pos, fs.getFileStatus(path).getLen())) - equality is allowed.","Re-stat the file immediately before seeking when files may change concurrently, and handle shrinkage (reopen/skip the split).","Validate externally supplied offsets (header-stored footer positions, config) against file length before seeking.","Catch EOFException around seek and treat as clean end-of-input for that reader."],"exampleFix":"// before\nin.seek(split.getEnd() + 1); // file shrank -> \"Cannot seek after EOF\"\n\n// after\nlong len = fs.getFileStatus(path).getLen();\nin.seek(Math.min(split.getEnd(), len));","handlingStrategy":"validation","validationCode":"long fileLen = fs.getFileStatus(path).getLen(); // re-stat: file may have changed\nlong target = Math.min(requestedPos, fileLen); // pos == fileLen is allowed\nif (requestedPos != target) {\n  LOG.warn(\"clamped seek {} -> {} for {}\", requestedPos, target, path);\n}\nin.seek(target);","typeGuard":null,"tryCatchPattern":"try {\n  in.seek(pos);\n} catch (EOFException e) {\n  if (\"Cannot seek after EOF\".equals(e.getMessage())) {\n    in.seek(fs.getFileStatus(path).getLen()); // treat as clean EOF\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always clamp seek targets to a freshly read file length","Re-stat files between split planning and reading when files can be rewritten concurrently","Validate header-stored offsets (footers, indices) against file length before seeking"],"tags":["hadoop","filesystem","io","seek","eof"],"backgroundTag":"seek-past-eof","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}