apache/hadoop · error · EOFException

Cannot seek to a negative offset

Error message

Cannot seek to a negative offset

What it means

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.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/RawLocalFileSystem.java:187

    /**
     * Thread level IOStatistics aggregator to update in close().
     */
    private final IOStatisticsAggregator
        ioStatisticsAggregator;

    public LocalFSFileInputStream(Path f) throws IOException {
      name = pathToFile(f);
      fis = new FileInputStream(name);
      bytesRead = ioStatistics.getCounterReference(
          STREAM_READ_BYTES);
      ioStatisticsAggregator =
          IOStatisticsContext.getCurrentIOStatisticsContext().getAggregator();
    }
    
    @Override
    public void seek(long pos) throws IOException {
      if (pos < 0) {
        throw new EOFException(
          FSExceptionMessages.NEGATIVE_SEEK);
      }
      fis.getChannel().position(pos);
      this.position = pos;
    }
    
    @Override
    public long getPos() throws IOException {
      return this.position;
    }
    
    @Override
    public boolean seekToNewSource(long targetPos) throws IOException {
      return false;
    }
    
    /**
     * Just forward to the fis.

View on GitHub (pinned to 2add963021)

Solutions

  1. Clamp the offset before seeking: long target = Math.max(0, desired); or if (desired < 0) seek(0).
  2. Fix the producer of the negative value: check the subtraction/split math and the index file contents that fed it.
  3. Guard against overflow: compute positions with Math.subtractExact or validate ranges on parsed offsets.
  4. If seeking to a position beyond EOF is part of your protocol, remember local files allow it, but below zero never is.

Example fix

// before
long target = currentPos - headerSize; // headerSize > currentPos -> negative
in.seek(target); // EOFException: Cannot seek to a negative offset

// after
long target = Math.max(0, currentPos - headerSize);
in.seek(target);
Defensive patterns

Strategy: validation

Validate before calling

public static void safeSeek(FSDataInputStream in, long pos) throws IOException {
  if (pos < 0) {
    throw new IllegalArgumentException("seek position must be >= 0, got " + pos);
  }
  in.seek(pos);
}

Try / catch

try {
  in.seek(offset);
} catch (EOFException e) {
  // negative offset is a caller bug; fix the computation, do not swallow
  throw new IllegalStateException("Bad offset computed: " + offset, e);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/0fab291d98892710. Report an issue: GitHub.