apache/hadoop · error · EOFException
Cannot seek to a negative offset
Error message
Cannot seek to a negative offset
What it means
Inside the bytebuffer block's ByteBufferInputStream.skip(offset), the new position is computed as position() + offset; if the result is negative the method throws EOFException(FSExceptionMessages.NEGATIVE_SEEK). Despite the 'seek' wording, this is triggered by skip(): skipping backwards by more than the current position inside an upload block buffer. It is a positional-arithmetic violation on an in-memory block, not a network or OBS service error.
Source
Thrown at hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSDataBlocks.java:713
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
}
public synchronized int read() {
if (available() > 0) {
return byteBuffer.get() & OBSCommonUtils.BYTE_TO_INT_MASK;
} else {
return -1;
}
}
@Override
public synchronized long skip(final long offset)
throws IOException {
verifyOpen();
long newPos = position() + offset;
if (newPos < 0) {
throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);
}
if (newPos > size) {
throw new EOFException(
FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
}
byteBuffer.position((int) newPos);
return newPos;
}
@Override
public synchronized int available() {
Preconditions.checkState(byteBuffer != null,
FSExceptionMessages.STREAM_IS_CLOSED);
return byteBuffer.remaining();
}
/**
* Get the current buffer position.View on GitHub (pinned to 2add963021)
Solutions
- Clamp the desired new position before calling skip: compute target = max(0, currentPosition + delta) and skip(target - currentPosition)
- Guard at the API boundary: reject or normalize negative skip requests before they reach the block stream
- If rewinding is genuinely needed, re-open the block stream from its start instead of using negative skip
Example fix
// before long skipped = blockStream.skip(delta); // delta may push position < 0 // after long pos = blockStream.position(); long clamped = Math.max(0, pos + delta); long skipped = blockStream.skip(clamped - pos);
Defensive patterns
Strategy: validation
Validate before calling
// before calling skip(delta) on a block stream
long target = currentPosition() + delta;
if (target < 0) {
target = 0; // or reject: throw new IllegalArgumentException("skip underflows position");
}
long toSkip = target - currentPosition();
if (toSkip != 0) blockStream.skip(toSkip); Try / catch
try {
blockStream.skip(delta);
} catch (EOFException e) {
if (FSExceptionMessages.NEGATIVE_SEEK.equals(e.getMessage())) {
// rewind past start requested: clamp to 0 and skip(-position) once
blockStream.skip(-blockStream.position());
} else {
throw e;
}
} Prevention
- Never pass unclamped relative deltas to skip()
- Track positions in your reader rather than trusting skip to bound-check
- Unit-test skip at position 0 and at block boundaries
When it happens
Trigger: Calling skip(n) where n is negative and |n| > current position within the block stream (e.g. at position 5, skip(-10)); passing a negative skip value directly; wrapper frameworks (record readers, compression codecs) that compute relative skips and occasionally go below zero.
Common situations: Custom InputStream wrappers that forward user-supplied offsets to skip(); record boundary resync logic that rewinds by a delta larger than bytes consumed; porting code from streams where negative skip is silently clamped to zero.
Related errors
- Attempted to seek or read past the end of the file
- Requested more bytes than destination buffer size: request l
- Cannot seek to a negative offset {}
- Unsupported block buffer "{}"
- Stream is closed!
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/d1b0dc8303827163.
Report an issue: GitHub.