apache/hadoop · error · EOFException

Cannot seek after EOF

Error message

Cannot seek after EOF

What it means

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.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ChecksumFileSystem.java:612

      return super.skip(n);
    }

    /**
     * Seek to the given position in the stream.
     * The next read() will be from that position.
     *
     * <p>This method does not allow seek past the end of the file.
     * This produces IOException.
     *
     * @param      pos   the postion to seek to.
     * @exception  IOException  if an I/O error occurs or seeks after EOF
     *             ChecksumException if the chunk to seek to is corrupted
     */

    @Override
    public synchronized void seek(long pos) throws IOException {
      if (pos > getFileLength()) {
        throw new EOFException("Cannot seek after EOF");
      }
      super.seek(pos);
    }

  }

  /**
   * Opens an FSDataInputStream at the indicated Path.
   * @param f the file name to open
   * @param bufferSize the size of the buffer to be used.
   * @throws IOException if an I/O error occurs.
   */
  @Override
  public FSDataInputStream open(Path f, int bufferSize) throws IOException {
    FileSystem fs;
    InputStream in;
    if (verifyChecksum) {
      fs = this;

View on GitHub (pinned to 2add963021)

Solutions

  1. Clamp the seek target to the current file length: seek(Math.min(pos, fs.getFileStatus(path).getLen())) - equality is allowed.
  2. Re-stat the file immediately before seeking when files may change concurrently, and handle shrinkage (reopen/skip the split).
  3. Validate externally supplied offsets (header-stored footer positions, config) against file length before seeking.
  4. Catch EOFException around seek and treat as clean end-of-input for that reader.

Example fix

// before
in.seek(split.getEnd() + 1); // file shrank -> "Cannot seek after EOF"

// after
long len = fs.getFileStatus(path).getLen();
in.seek(Math.min(split.getEnd(), len));
Defensive patterns

Strategy: validation

Validate before calling

long fileLen = fs.getFileStatus(path).getLen(); // re-stat: file may have changed
long target = Math.min(requestedPos, fileLen); // pos == fileLen is allowed
if (requestedPos != target) {
  LOG.warn("clamped seek {} -> {} for {}", requestedPos, target, path);
}
in.seek(target);

Try / catch

try {
  in.seek(pos);
} catch (EOFException e) {
  if ("Cannot seek after EOF".equals(e.getMessage())) {
    in.seek(fs.getFileStatus(path).getLen()); // treat as clean EOF
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/647f96db2ab3400b. Report an issue: GitHub.