{"record":{"id":"0fab291d98892710","repo":"apache/hadoop","slug":"cannot-seek-to-a-negative-offset-0fab29","errorCode":null,"errorMessage":"Cannot seek to a negative offset","messagePattern":"Cannot seek to a negative offset","errorType":"validation","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/RawLocalFileSystem.java","lineNumber":187,"sourceCode":"    /**\n     * Thread level IOStatistics aggregator to update in close().\n     */\n    private final IOStatisticsAggregator\n        ioStatisticsAggregator;\n\n    public LocalFSFileInputStream(Path f) throws IOException {\n      name = pathToFile(f);\n      fis = new FileInputStream(name);\n      bytesRead = ioStatistics.getCounterReference(\n          STREAM_READ_BYTES);\n      ioStatisticsAggregator =\n          IOStatisticsContext.getCurrentIOStatisticsContext().getAggregator();\n    }\n    \n    @Override\n    public void seek(long pos) throws IOException {\n      if (pos < 0) {\n        throw new EOFException(\n          FSExceptionMessages.NEGATIVE_SEEK);\n      }\n      fis.getChannel().position(pos);\n      this.position = pos;\n    }\n    \n    @Override\n    public long getPos() throws IOException {\n      return this.position;\n    }\n    \n    @Override\n    public boolean seekToNewSource(long targetPos) throws IOException {\n      return false;\n    }\n    \n    /**\n     * Just forward to the fis.","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/RawLocalFileSystem.java#L169-L205","documentation":"RawLocalFileSystem's LocalFSFileInputStream.seek(long) throws EOFException (FSExceptionMessages.NEGATIVE_SEEK) whenever pos is negative, before it ever calls fis.getChannel().position(pos). The check protects the underlying FileChannel, which would otherwise throw an unspecified runtime exception. Negative offsets are always a caller bug: a computation (getPos() - n, a length subtraction, a signed overflow) produced a value below zero.","triggerScenarios":"Calling seek(pos) with pos < 0 on an FSDataInputStream over a local file: seek(getPos() - readAhead) where readAhead exceeds current position, seek(fileLen - offset) with offset > fileLen, a long underflow, or parsing a negative byte offset from user input or a split definition.","commonSituations":"Custom RecordReader implementations computing split start positions, readers implementing 'skip back N bytes' logic without clamping, index files whose recorded offsets exceed the file length, or Integer/Long arithmetic overflow making a positive value wrap negative.","solutions":["Clamp the offset before seeking: long target = Math.max(0, desired); or if (desired < 0) seek(0).","Fix the producer of the negative value: check the subtraction/split math and the index file contents that fed it.","Guard against overflow: compute positions with Math.subtractExact or validate ranges on parsed offsets.","If seeking to a position beyond EOF is part of your protocol, remember local files allow it, but below zero never is."],"exampleFix":"// before\nlong target = currentPos - headerSize; // headerSize > currentPos -> negative\nin.seek(target); // EOFException: Cannot seek to a negative offset\n\n// after\nlong target = Math.max(0, currentPos - headerSize);\nin.seek(target);","handlingStrategy":"validation","validationCode":"public static void safeSeek(FSDataInputStream in, long pos) throws IOException {\n  if (pos < 0) {\n    throw new IllegalArgumentException(\"seek position must be >= 0, got \" + pos);\n  }\n  in.seek(pos);\n}","typeGuard":null,"tryCatchPattern":"try {\n  in.seek(offset);\n} catch (EOFException e) {\n  // negative offset is a caller bug; fix the computation, do not swallow\n  throw new IllegalStateException(\"Bad offset computed: \" + offset, e);\n}","preventionTips":["Clamp computed offsets with Math.max(0, value) before seek.","Validate parsed byte offsets from index files against [0, fileLength].","Use Math.subtractExact for position arithmetic to surface overflow as an exception at the source."],"tags":["hadoop","local-filesystem","seek","offset","eofexception","input-stream"],"backgroundTag":"negative-offset-seek","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}