{"record":{"id":"bd09bd419109b5d0","repo":"apache/hadoop","slug":"cannot-seek-to-a-negative-offset","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-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNInputStream.java","lineNumber":148,"sourceCode":"    this.key = key;\n    this.fileSize = fileSize;\n    this.preReadPartSize = conf.getLong(\n        CosNConfigKeys.READ_AHEAD_BLOCK_SIZE_KEY,\n        CosNConfigKeys.DEFAULT_READ_AHEAD_BLOCK_SIZE);\n    this.maxReadPartNumber = conf.getInt(\n        CosNConfigKeys.READ_AHEAD_QUEUE_SIZE,\n        CosNConfigKeys.DEFAULT_READ_AHEAD_QUEUE_SIZE);\n\n    this.readAheadExecutorService = readAheadExecutorService;\n    this.readBufferQueue = new ArrayDeque<>(this.maxReadPartNumber);\n    this.closed = false;\n  }\n\n  private synchronized void reopen(long pos) throws IOException {\n    long partSize;\n\n    if (pos < 0) {\n      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);\n    } else if (pos > this.fileSize) {\n      throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);\n    } else {\n      if (pos + this.preReadPartSize > this.fileSize) {\n        partSize = this.fileSize - pos;\n      } else {\n        partSize = this.preReadPartSize;\n      }\n    }\n\n    this.buffer = null;\n\n    boolean isRandomIO = true;\n    if (pos == this.nextPos) {\n      isRandomIO = false;\n    } else {\n      while (this.readBufferQueue.size() != 0) {\n        if (this.readBufferQueue.element().getStart() != pos) {","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNInputStream.java#L130-L166","documentation":"CosNInputStream.reopen(position) validates the requested byte position before refilling its read buffer; a negative position raises EOFException('Cannot seek to a negative offset') from FSExceptionMessages.NEGATIVE_SEEK. reopen is driven by seek() and by reads whose target falls outside the current buffer, so offset arithmetic that goes below zero surfaces here. Note seek() also has its own earlier guard, so this site is reached through internal repositioning.","triggerScenarios":"Computed offsets like pos - readLen underflowing below zero; skip() combined with seek near the file start; custom RecordReaders deriving split start positions that go negative.","commonSituations":"Custom input formats computing seek targets (split start minus header length); off-by-one after skip; downstream code assuming getPos() can be rewound arbitrarily.","solutions":["Clamp the position: seek(Math.max(0, pos)).","Log pos before seeking and fix the arithmetic that produces negative values.","Validate the target against the file length from getFileStatus(p).getLen() before seeking."],"exampleFix":"// before\nlong target = currentPos - headerLen; // may be negative\nin.seek(target); // EOFException: Cannot seek to a negative offset\n\n// after\nlong target = Math.max(0, currentPos - headerLen);\nin.seek(target);","handlingStrategy":"validation","validationCode":"long len = fs.getFileStatus(p).getLen();\nif (target < 0) { target = 0; }\nif (target > len) { target = len; }\nin.seek(target);","typeGuard":"static boolean isNegativeSeek(Throwable t) {\n  return t instanceof EOFException && t.getMessage() != null\n      && t.getMessage().contains('negative');\n}","tryCatchPattern":"try {\n  in.seek(pos);\n} catch (EOFException e) {\n  if (pos < 0) { in.seek(0); } else { throw e; }\n}","preventionTips":["Clamp seek targets to [0, fileLength] before calling seek","Log computed offsets in custom readers to catch underflow early","Treat a negative offset as a bug in caller arithmetic, not transient IO"],"tags":["cosn","hadoop","input-stream","seek","negative-offset"],"backgroundTag":"negative-seek-offset","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}