apache/hadoop · error · EOFException

Invalid seek offset: position value (%d) must be >= 0 for '%

Error message

Invalid seek offset: position value (%d) must be >= 0 for '%s'

What it means

validatePosition throws EOFException when the requested seek position is negative. Any channel position must be >= 0; the check runs before the objectSize range check. Note the exception type is EOFException rather than IllegalArgumentException — chosen so Hadoop-side seek/position callers treat it as a read-position failure.

Source

Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorageClientReadChannel.java:589

  }

  private IOException convertError(Exception error) {
    String msg = String.format("Error reading '%s'", resourceId);
    switch (ErrorTypeExtractor.getErrorType(error)) {
    case NOT_FOUND:
      return createFileNotFoundException(
          resourceId.getBucketName(), resourceId.getObjectName(), new IOException(msg, error));
    case OUT_OF_RANGE:
      return (IOException) new EOFException(msg).initCause(error);
    default:
      return new IOException(msg, error);
    }
  }

  /** Validates that the given position is valid for this channel. */
  private void validatePosition(long position) throws IOException {
    if (position < 0) {
      throw new EOFException(
          String.format(
              "Invalid seek offset: position value (%d) must be >= 0 for '%s'",
              position, resourceId));
    }

    if (objectSize >= 0 && position >= objectSize) {
      throw new EOFException(
          String.format(
              "Invalid seek offset: position value (%d) must be between 0 and %d for '%s'",
              position, objectSize, resourceId));
    }
  }

  /** Throws if this channel is not currently open. */
  private void throwIfNotOpen() throws IOException {
    if (!isOpen()) {
      throw new ClosedChannelException();
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Validate/clamp offsets to >= 0 before calling position/seek.
  2. Fix the underflow arithmetic (guard subtractions, use Math.max(0, candidate)).
  3. Treat occurrence as a caller bug: add a precondition in your position-tracking code.

Example fix

// before
long target = currentPos - overshoot; // can go negative
ch.position(target);

// after
long target = Math.max(0, currentPos - overshoot);
ch.position(target);
Defensive patterns

Strategy: validation

Validate before calling

long safeTarget = Math.max(0, computedOffset);
if (safeTarget != computedOffset) LOG.warn("clamped negative offset {} -> 0", computedOffset);
ch.position(safeTarget);

Prevention

When it happens

Trigger: Calling position(negative) on the client read channel — offsets produced by underflowing arithmetic such as pos - bytesRead going below zero, or record readers computing a previous-marker incorrectly.

Common situations: Off-by-one/underflow bugs in split-offset math in custom InputFormats; position bookkeeping that subtracts more than the current position; ported code assuming clamping semantics.

Related errors


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