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
- Validate/clamp offsets to >= 0 before calling position/seek.
- Fix the underflow arithmetic (guard subtractions, use Math.max(0, candidate)).
- 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
- Guard every subtraction used for positions with Math.max(0, ...).
- Unit-test offset math with boundary inputs (0-position reads, overshoot larger than position).
- Treat negative-seek as a caller bug in logs — fix the arithmetic, don't clamp in production silently.
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
- Invalid seek offset: position value (%d) must be between 0 a
- Cannot seek to a negative offset " + targetPos
- Cannot seek to a negative offset
- Bucket doesn't match for source '%s' and destination '%s'!
- Bucket not found: %s
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/4179b6524b92d5d3.
Report an issue: GitHub.