{"record":{"id":"8a1b54df14c9a798","repo":"apache/hadoop","slug":"offset-0-offset-getfilelength-offset","errorCode":null,"errorMessage":"offset < 0 || offset >= getFileLength(), offset={}, locatedBlocks={}","messagePattern":"offset < 0 \\|\\| offset >= getFileLength\\(\\), offset=(.+?), locatedBlocks=(.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DFSInputStream.java","lineNumber":479,"sourceCode":"  }\n\n  /**\n   * Get block at the specified position.\n   * Fetch it from the namenode if not cached.\n   *\n   * @param offset block corresponding to this offset in file is returned\n   * @return located block\n   * @throws IOException\n   */\n  protected LocatedBlock getBlockAt(long offset) throws IOException {\n    synchronized(infoLock) {\n      assert (locatedBlocks != null) : \"locatedBlocks is null\";\n\n      final LocatedBlock blk;\n\n      //check offset\n      if (offset < 0 || offset >= getFileLength()) {\n        throw new IOException(\"offset < 0 || offset >= getFileLength(), offset=\"\n            + offset\n            + \", locatedBlocks=\" + locatedBlocks);\n      }\n      else if (offset >= locatedBlocks.getFileLength()) {\n        // offset to the portion of the last block,\n        // which is not known to the name-node yet;\n        // getting the last block\n        blk = locatedBlocks.getLastLocatedBlock();\n      }\n      else {\n        // search cached blocks first\n        blk = fetchBlockAt(offset, 0, true);\n      }\n      return blk;\n    }\n  }\n\n  /** Fetch a block from namenode and cache it */","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DFSInputStream.java#L461-L497","documentation":"getBlockAt() hard-validates that the requested byte offset lies in [0, getFileLength()) before locating the block. An offset outside that range throws immediately. Since the check uses the client's current view of the length, it fires both on genuine caller bugs (negative or past-EOF offsets) and on stale-length races where the file was truncated after the stream cached its length.","triggerScenarios":"seek()/read paths computing an offset >= current file length (or < 0); file truncated by another client between the client's last length refresh and this call.","commonSituations":"Reader arithmetic that assumes a longer file (stale FileStatus); concurrent truncate racing a tailer; off-by-one loop bounds in custom readers.","solutions":["Clamp offsets into [0, length-1] using a freshly fetched file length before seeking/reading","Re-fetch getFileStatus().getLen() after any event that can shrink the file (truncate by another writer)","Fix caller-side math that produces negative offsets (usually underflow after subtraction)"],"exampleFix":"// before\nlong offset = end - remaining; // can go negative or past EOF\nin.seek(offset);\n\n// after\nlong len = fs.getFileStatus(path).getLen();\nlong offset = Math.max(0, Math.min(end - remaining, len - 1));\nin.seek(offset);","handlingStrategy":"validation","validationCode":"long len = fs.getFileStatus(path).getLen();\nif (offset < 0 || offset >= len) {\n  throw new IllegalArgumentException(\"offset \" + offset + \" outside [0,\" + len + \")\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  in.seek(offset);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"offset < 0\")) {\n    long len = fs.getFileStatus(path).getLen();\n    in.seek(Math.max(0, Math.min(offset, len - 1)));\n  } else throw e;\n}","preventionTips":["Always bounds-check computed offsets against a fresh file length","Re-stat files that other clients can truncate before seeking","Watch for unsigned underflow when computing offsets by subtraction"],"tags":["hdfs","offset","validation","read"],"backgroundTag":"offset-out-of-range","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}