apache/hadoop · error · EOFException

Cannot seek to a negative offset

Error message

Cannot seek to a negative offset

What it means

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.

Source

Thrown at hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNInputStream.java:148

    this.key = key;
    this.fileSize = fileSize;
    this.preReadPartSize = conf.getLong(
        CosNConfigKeys.READ_AHEAD_BLOCK_SIZE_KEY,
        CosNConfigKeys.DEFAULT_READ_AHEAD_BLOCK_SIZE);
    this.maxReadPartNumber = conf.getInt(
        CosNConfigKeys.READ_AHEAD_QUEUE_SIZE,
        CosNConfigKeys.DEFAULT_READ_AHEAD_QUEUE_SIZE);

    this.readAheadExecutorService = readAheadExecutorService;
    this.readBufferQueue = new ArrayDeque<>(this.maxReadPartNumber);
    this.closed = false;
  }

  private synchronized void reopen(long pos) throws IOException {
    long partSize;

    if (pos < 0) {
      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);
    } else if (pos > this.fileSize) {
      throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
    } else {
      if (pos + this.preReadPartSize > this.fileSize) {
        partSize = this.fileSize - pos;
      } else {
        partSize = this.preReadPartSize;
      }
    }

    this.buffer = null;

    boolean isRandomIO = true;
    if (pos == this.nextPos) {
      isRandomIO = false;
    } else {
      while (this.readBufferQueue.size() != 0) {
        if (this.readBufferQueue.element().getStart() != pos) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Clamp the position: seek(Math.max(0, pos)).
  2. Log pos before seeking and fix the arithmetic that produces negative values.
  3. Validate the target against the file length from getFileStatus(p).getLen() before seeking.

Example fix

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

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

Strategy: validation

Validate before calling

long len = fs.getFileStatus(p).getLen();
if (target < 0) { target = 0; }
if (target > len) { target = len; }
in.seek(target);

Type guard

static boolean isNegativeSeek(Throwable t) {
  return t instanceof EOFException && t.getMessage() != null
      && t.getMessage().contains('negative');
}

Try / catch

try {
  in.seek(pos);
} catch (EOFException e) {
  if (pos < 0) { in.seek(0); } else { throw e; }
}

Prevention

When it happens

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

Common situations: Custom input formats computing seek targets (split start minus header length); off-by-one after skip; downstream code assuming getPos() can be rewound arbitrarily.

Related errors


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