{"record":{"id":"554aedaef694ceb8","repo":"apache/hadoop","slug":"cannot-seek-to-a-negative-offset-targetpos","errorCode":null,"errorMessage":"Cannot seek to a negative offset \" + targetPos","messagePattern":"Cannot seek to a negative offset \" \\+ 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":275,"sourceCode":"      super.close();\n    }\n  }\n\n  /**\n   * 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  /**","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BosInputStream.java#L257-L293","documentation":"BosInputStream.seek(long) throws EOFException carrying FSExceptionMessages.NEGATIVE_SEEK plus the target position when targetPos < 0. Note the exception type: Hadoop convention reports a bad seek argument as EOFException even though the input is invalid, and checkNotClosed() has already run, so a closed stream fails with a different message first.","triggerScenarios":"Calling seek() with a negative value — usually a computed position like (previousLineStart - delimiterLength) that underflows, or a -1 sentinel from an upstream API forwarded straight into seek.","commonSituations":"Custom RecordReaders that rewind by 'pos - 1' to resync delimiters; long arithmetic where a length exceeds the current position; passing 'not found' sentinels (-1) from index lookups into seek.","solutions":["Clamp the target: long p = Math.max(0, targetPos); when negative means 'start of file'","Audit position arithmetic for underflow: if (target < 0) target = 0; before calling seek","Translate upstream -1 sentinels into explicit control flow instead of forwarding them to seek"],"exampleFix":"// before\nin.seek(pos - delimiterLen); // underflows when pos < delimiterLen\n\n// after\nin.seek(Math.max(0, pos - delimiterLen));","handlingStrategy":"validation","validationCode":"long safeTarget = Math.max(0, requestedPos);\nif (requestedPos < 0) LOG.warn(\"clamping negative seek {} to 0\", requestedPos);\nin.seek(safeTarget);","typeGuard":null,"tryCatchPattern":"catch (EOFException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"negative\")) {\n    in.seek(0); // recover: restart from beginning for this record\n  } else { throw e; }\n}","preventionTips":["Validate positions against >= 0 before every seek","Audit pos - n arithmetic for underflow in record readers","Never forward -1 sentinels from lookups into seek"],"tags":["bos","input-stream","seek","negative-offset","hadoop"],"backgroundTag":"invalid-seek-offset","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}