apache/hadoop · error · EOFException

position is negative in range {range}

Error message

position is negative in range {range}

What it means

Thrown by VectoredReadUtils.validateRangeRequest when a FileRange submitted to a vectored read has a negative offset. Per the method's contract (and slightly unusually), a negative offset raises EOFException while a negative length raises IllegalArgumentException. Validation runs inside validateAndSortRanges/readVectored before any I/O, so this always indicates a caller bug constructing ranges, not a stream condition.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/VectoredReadUtils.java:83

  /**
   * Validate a single range.
   * @param range range to validate.
   * @return the range.
   * @param <T> range type
   * @throws IllegalArgumentException the range length is negative or other invalid condition
   * is met other than the those which raise EOFException or NullPointerException.
   * @throws EOFException the range offset is negative
   * @throws NullPointerException if the range is null.
   */
  public static <T extends FileRange> T validateRangeRequest(T range)
          throws EOFException {

    requireNonNull(range, "range is null");

    checkArgument(range.getLength() >= 0, "length is negative in %s", range);
    if (range.getOffset() < 0) {
      throw new EOFException("position is negative in range " + range);
    }
    return range;
  }

  /**
   * Validate a list of vectored read ranges.
   * @param ranges list of ranges.
   * @throws EOFException any EOF exception.
   */
  public static void validateVectoredReadRanges(List<? extends FileRange> ranges)
          throws EOFException {
    validateAndSortRanges(ranges, Optional.empty());
  }

  /**
   * This is the default implementation which iterates through the ranges
   * to read each synchronously, but the intent is that subclasses
   * can make more efficient readers.

View on GitHub (pinned to 2add963021)

Solutions

  1. Fix the range construction: clamp or reject offsets < 0 before creating FileRange objects
  2. Check intermediate arithmetic for underflow (use Math.max(0, pos - delta)) and for int-to-long sign extension
  3. Validate the whole list up front with VectoredReadUtils.validateVectoredReadRanges so failures surface at range-build time with full context

Example fix

// before
long offset = index * chunkSize - delta; // may go negative
FileRange r = FileRange.createFileRange(offset, len);

// after
long offset = Math.max(0L, index * chunkSize - delta);
if (offset < 0L || len < 0) {
  throw new IllegalArgumentException("Invalid range: offset=" + offset + " len=" + len);
}
FileRange r = FileRange.createFileRange(offset, len);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidRange(long offset, int len) {
  return offset >= 0 && len >= 0;
}

List<FileRange> safe = new ArrayList<>();
for (FileRange r : ranges) {
  if (isValidRange(r.getOffset(), r.getLength())) {
    safe.add(r);
  } else {
    throw new IllegalArgumentException("Bad range: offset=" + r.getOffset()
        + " len=" + r.getLength());
  }
}
fs.readVectored(f, safe, allocate);

Try / catch

try {
  VectoredReadUtils.validateVectoredReadRanges(ranges);
} catch (EOFException e) {
  // "position is negative in range ..." -> range-construction bug upstream
  throw new IllegalArgumentException("Ranges built with negative offset", e);
} catch (IllegalArgumentException e) {
  // negative length or overlapping ranges
  throw e;
}

Prevention

When it happens

Trigger: fs.readVectored(stream, ranges) / validateVectoredReadRanges where a FileRange was built with offset < 0: chunk-offset arithmetic underflow (index * chunkSize - delta), signed overflow of a long computed from an int, or parsing a negative offset from user input.

Common situations: Custom columnar/parquet readers computing stripe offsets; unit tests generating ranges at boundaries; code ported from an API where negative offsets wrapped around.

Related errors


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