apache/hadoop · error · EOFException

Cannot seek to a negative offset " + pos

Error message

Cannot seek to a negative offset " + pos

What it means

S3ARemoteInputStream.throwIfInvalidSeek() throws EOFException(FSExceptionMessages.NEGATIVE_SEEK + " " + pos) when seek() is called with a position < 0. The stream serves block data of a prefetched S3 object, and negative offsets are meaningless; this is a caller arithmetic bug.

Source

Thrown at hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/prefetch/S3ARemoteInputStream.java:463

      return "closed";
    }

    StringBuilder sb = new StringBuilder();
    sb.append(String.format("nextReadPos = (%d)%n", nextReadPos));
    sb.append(String.format("fpos = (%s)", fpos));
    return sb.toString();
  }

  protected void throwIfClosed() throws IOException {
    if (closed) {
      throw new IOException(
          name + ": " + FSExceptionMessages.STREAM_IS_CLOSED);
    }
  }

  protected void throwIfInvalidSeek(long pos) throws EOFException {
    if (pos < 0) {
      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK + " " + pos);
    } else if (pos > this.getBlockData().getFileSize()) {
      throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF + " " + pos);
    }
  }

  // Unsupported functions.

  @Override
  public void mark(int readlimit) {
    throw new UnsupportedOperationException("mark not supported");
  }

  @Override
  public void reset() {
    throw new UnsupportedOperationException("reset not supported");
  }

  @Override

View on GitHub (pinned to 2add963021)

Solutions

  1. Clamp seek targets to >= 0 before calling seek().
  2. Audit offset arithmetic (subtractions, casting int->long) that feeds seek positions.
  3. Prefer FSDataInputStream.seekToNewSource-style guarded APIs or check getPos() first.
  4. Write a unit test asserting all computed seek offsets are within [0, fileLen).

Example fix

// before
long pos = split.getStart() - prefixLen; // may be negative
in.seek(pos);

// after
long pos = Math.max(0, split.getStart() - prefixLen);
in.seek(pos);
Defensive patterns

Strategy: validation

Validate before calling

if (pos < 0) {
  throw new IllegalArgumentException("seek position must be >= 0, got " + pos);
}
in.seek(pos);

Try / catch

try {
  in.seek(pos);
} catch (EOFException e) {
  LOG.error("invalid seek to {}", pos, e); // caller arithmetic bug
  throw e;
}

Prevention

When it happens

Trigger: seek() with a negative computed offset on a stream using the prefetcher (fs.s3a.input.stream.type=Prefetch); offset underflow in custom split/RecordReader math; passing -1 'not set' sentinels from higher layers into seek.

Common situations: RecordReaders computing (splitStart - headerBytes); code ported from local-file assumptions; retry logic seeking to previous positions after consuming the whole stream (getPos semantics confusion).

Related errors


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