{"record":{"id":"832c94cae298f5bd","repo":"apache/hadoop","slug":"attempted-to-seek-or-read-past-the-end-of-the-file","errorCode":null,"errorMessage":"Attempted to seek or read past the end of the file \" + targetPos","messagePattern":"Attempted to seek or read past the end of the file \" \\+ targetPos","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BosInputStream.java","lineNumber":280,"sourceCode":"   * Seeks to the specified position in the stream. This\n   * performs a lazy seek; the actual stream repositioning\n   * happens on the next read.\n   *\n   * @param targetPos the target position to seek to\n   * @throws IOException if an I/O error occurs\n   */\n  public synchronized void seek(long targetPos)\n      throws IOException {\n    checkNotClosed();\n\n    // Do not allow negative seek\n    if (targetPos < 0) {\n      throw new EOFException(\n          FSExceptionMessages.NEGATIVE_SEEK\n              + \" \" + targetPos);\n    }\n    if (targetPos > contentLength) {\n      throw new EOFException(\n          FSExceptionMessages.CANNOT_SEEK_PAST_EOF\n              + \" \" + targetPos);\n    }\n\n    if (this.contentLength <= 0) {\n      return;\n    }\n\n    // Lazy seek\n    nextReadPos = targetPos;\n  }\n\n  /**\n   * Returns the current position in the stream.\n   *\n   * @return the current position\n   * @throws IOException if an I/O error occurs\n   */","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BosInputStream.java#L262-L298","documentation":"seek() throws EOFException with FSExceptionMessages.CANNOT_SEEK_PAST_EOF plus the target when targetPos > contentLength, using the object size captured when the stream was opened. No read is attempted. Because the bound is the cached contentLength, a stale view of a concurrently rewritten (smaller) object also triggers it. Note the check is strict '>': seeking exactly to length is allowed and returns EOF on the next read.","triggerScenarios":"Seeking to a position derived from a different or older version of the object; a file that was overwritten with a shorter one between open() and seek(); off-by-one logic that treats length+1 as 'one past end'.","commonSituations":"Reading files that writers rewrite in place (violating immutability expectations); lengths cached from FileStatus before an overwrite; format readers computing end positions from separately-fetched metadata.","solutions":["Re-stat the path (fs.getFileStatus) immediately before open() if concurrent writes are possible, and open a fresh stream","Clamp the target to contentLength and treat read() == -1 as the end-of-file signal instead of seeking past it","Ensure writers write once to a new key (rename/copy-then-swap) so readers never see a shrinking object"],"exampleFix":"// before\nin.seek(offsetFromStaleMetadata);\n\n// after\nlong len = fs.getFileStatus(path).getLen();\nin.seek(Math.min(offsetFromStaleMetadata, len));","handlingStrategy":"validation","validationCode":"long len = fs.getFileStatus(path).getLen(); // fresh length\nin.seek(Math.min(targetPos, len));","typeGuard":null,"tryCatchPattern":"catch (EOFException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"past the end\")) {\n    // object shrank or position is stale: re-stat and reopen\n    reopenFrom(fs.getFileStatus(path).getLen());\n  } else { throw e; }\n}","preventionTips":["Re-stat files before opening when concurrent rewrites are possible","Writers use new keys per version (copy-then-swap), never truncate in place","Treat read() == -1 as EOF instead of seeking past the known length"],"tags":["bos","input-stream","seek","eof","hadoop"],"backgroundTag":"seek-past-eof","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}