{"record":{"id":"462c3136c1fade8b","repo":"apache/hadoop","slug":"cannot-seek-to-a-negative-offset-s","errorCode":null,"errorMessage":"Cannot seek to a negative offset %s","messagePattern":"Cannot seek to a negative offset (.+?)","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/ObjectMultiRangeInputStream.java","lineNumber":81,"sourceCode":"      ObjectStorage storage,\n      String objectKey,\n      long contentLength,\n      long rangeSize,\n      byte[] checksum) {\n    this.threadPool = threadPool;\n    this.storage = storage;\n    this.objectKey = objectKey;\n    this.contentLength = contentLength;\n    this.rangeSize = rangeSize;\n    this.checksum = checksum;\n\n    Preconditions.checkNotNull(checksum, \"Checksum should not be null.\");\n  }\n\n  @Override\n  public synchronized void seek(long pos) throws IOException {\n    if (pos < 0) {\n      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK + \" \" + pos);\n    }\n\n    if (contentLength <= 0) {\n      return;\n    }\n\n    nextPos = pos;\n  }\n\n  @Override\n  public synchronized long getPos() {\n    return nextPos;\n  }\n\n  @Override\n  public synchronized boolean seekToNewSource(long targetPos) throws IOException {\n    checkNotClosed();\n    return false;","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/ObjectMultiRangeInputStream.java#L63-L99","documentation":"ObjectMultiRangeInputStream is the seekable reader that serves an object through sequential range GETs. seek(pos) rejects negative positions with EOFException carrying FSExceptionMessages.NEGATIVE_SEEK (\"Cannot seek to a negative offset <pos>\"), mirroring the HDFS/FSDataInputStream contract. Seeking past EOF is allowed (the position is stored and validated lazily on the next read); only negative positions throw.","triggerScenarios":"Calling seek() with a negative value: seek(-1) directly, arithmetic like seek(getPos() - n) underflowing, or passing a -1 sentinel from an API that uses -1 to mean 'unknown'.","commonSituations":"Custom FSDataInputStream wrappers computing relative offsets by subtraction; off-by-one bugs in range loops over file splits; reusing a -1 length/offset result as a position.","solutions":["Clamp positions to >= 0 before calling seek (Math.max(0, pos))","Fix the offset arithmetic that produced the negative value (usually subtracting a chunk larger than the remaining bytes)","Treat -1 sentinels from length/position APIs as EOF, never as a seek target"],"exampleFix":"// before\nin.seek(pos);\n\n// after\nif (pos < 0) {\n  throw new IllegalArgumentException(\"seek position must be >= 0: \" + pos);\n}\nin.seek(pos);","handlingStrategy":"validation","validationCode":"if (pos < 0) {\n  throw new IllegalArgumentException(\"seek position must be >= 0: \" + pos);\n}\nin.seek(pos);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate offsets at API boundaries before seeking","Never pass -1 sentinels to seek()","Base relative seeks on getPos(), clamped to >= 0"],"tags":["hadoop-tos","object-storage","input-stream","seek","negative-offset"],"backgroundTag":"negative-seek","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}