{"record":{"id":"c1b2e8012ffb11ae","repo":"apache/hadoop","slug":"cannot-seek-to-a-negative-offset-c1b2e8","errorCode":null,"errorMessage":"Cannot seek to a negative offset","messagePattern":"Cannot seek to a negative offset","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/BufferedFSInputStream.java","lineNumber":87,"sourceCode":"  }\n\n  @Override\n  public long skip(long n) throws IOException {\n    if (n <= 0) {\n      return 0;\n    }\n\n    seek(getPos()+n);\n    return n;\n  }\n\n  @Override\n  public void seek(long pos) throws IOException {\n    if (in == null) {\n      throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);\n    }\n    if (pos < 0) {\n      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);\n    }\n    if (this.pos != this.count) {\n      // optimize: check if the pos is in the buffer\n      // This optimization only works if pos != count -- if they are\n      // equal, it's possible that the previous reads were just\n      // longer than the total buffer size, and hence skipped the buffer.\n      long end = ((FSInputStream)in).getPos();\n      long start = end - count;\n      if( pos>=start && pos<end) {\n        this.pos = (int)(pos-start);\n        return;\n      }\n    }\n\n    // invalidate buffer\n    this.pos = 0;\n    this.count = 0;\n","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/BufferedFSInputStream.java#L69-L105","documentation":"BufferedFSInputStream.seek throws EOFException with FSExceptionMessages.NEGATIVE_SEEK (\"Cannot seek to a negative offset\") whenever the requested position is negative. Besides passing a literal negative offset, the classic route is arithmetic: skip(n) computes getPos()+n, and with n near Long.MAX_VALUE the sum overflows to a negative value; int-to-long conversion mistakes on files larger than 2 GiB produce the same result.","triggerScenarios":"seek(offset - headerLength) where the subtraction underflows at small offsets; computing positions with int arithmetic and casting to long for >2 GiB files; skip(hugeN) wrapping around through overflow; user-supplied offsets parsed from malformed config without range checks.","commonSituations":"Split/offset math in custom input formats for files bigger than Integer.MAX_VALUE; seek-back logic like seek(pos - bytesRequested) at file start; tools accepting arbitrary seek offsets from the command line or a manifest.","solutions":["Clamp the target before seeking: seek(Math.max(0, target)).","Use long arithmetic throughout and Math.addExact/subtractExact (or explicit range checks) around offset math so overflow fails loudly instead of silently producing negative values.","Validate external offsets (CLI args, config) as non-negative and within file length before use.","Fix skip() call sites that pass huge counts; cap n or check for overflow before calling skip."],"exampleFix":"// before\nlong start = offset - trailingHeaderLen;\nin.seek(start); // EOFException: Cannot seek to a negative offset\n\n// after\nlong start = Math.max(0, offset - trailingHeaderLen);\nin.seek(start);","handlingStrategy":"validation","validationCode":"static long clampSeek(long target, long fileLen) {\n  if (target < 0) return 0;\n  return Math.min(target, fileLen);\n}\n// call: in.seek(clampSeek(offset - headerLen, fileLen));","typeGuard":null,"tryCatchPattern":"try {\n  in.seek(target);\n} catch (EOFException e) {\n  if (FSExceptionMessages.NEGATIVE_SEEK.equals(e.getMessage())) {\n    throw new IllegalArgumentException(\"seek target underflow: \" + target, e);\n  }\n  throw e;\n}","preventionTips":["Use long (never int) for all offset arithmetic on large files","Wrap sums/differences in Math.addExact/Math.subtractExact so overflow fails loudly","Validate user/config-supplied offsets as non-negative before use","Remember skip(n) computes getPos()+n: guard huge n against wraparound"],"tags":["hadoop","filesystem","io","seek","integer-overflow"],"backgroundTag":"negative-seek-offset","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}