apache/hadoop · error · EOFException
Cannot seek to negative offset
Error message
Cannot seek to negative offset
What it means
DFSInputStream.seek(long) validates the requested position before doing anything: any targetPos < 0 throws java.io.EOFException('Cannot seek to negative offset'). HDFS files start at offset 0, so a negative target is always a caller bug (bad offset arithmetic), not a transient cluster condition. Note the odd choice of EOFException, which pairs it with the 'Cannot seek after EOF' check just above it.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DFSInputStream.java:1645
if (n+curPos > fileLen) {
n = fileLen - curPos;
}
seek(curPos+n);
return n;
}
return n < 0 ? -1 : 0;
}
/**
* Seek to a new arbitrary location
*/
@Override
public synchronized void seek(long targetPos) throws IOException {
if (targetPos > getFileLength()) {
throw new EOFException("Cannot seek after EOF");
}
if (targetPos < 0) {
throw new EOFException("Cannot seek to negative offset");
}
if (closed.get()) {
throw new IOException("Stream is closed!");
}
boolean done = false;
if (pos <= targetPos && targetPos <= blockEnd) {
//
// If this seek is to a positive position in the current
// block, and this piece of data might already be lying in
// the TCP buffer, then just eat up the intervening data.
//
int diff = (int)(targetPos - pos);
if (diff <= blockReader.available()) {
try {
pos += blockReader.skip(diff);
if (pos == targetPos) {
done = true;
} else {View on GitHub (pinned to 2add963021)
Solutions
- Fix the offset arithmetic so it can never go below 0: clamp with Math.max(0, computedPos) before calling seek().
- Audit every expression feeding seek() for subtraction that can underflow (pos - headerLen, splitStart - 1, pos - recordLen) and guard each one.
- If the negative value comes from parsed metadata, validate it and fail fast with a clear message about the corrupt index instead of letting seek() throw.
- Add a boundary unit test at position 0 and position 1 to lock in the clamping behavior.
Example fix
// before long prevStart = in.getPos() - recordHeaderLen; in.seek(prevStart); // throws when getPos() < recordHeaderLen // after long prevStart = Math.max(0, in.getPos() - recordHeaderLen); in.seek(prevStart);
Defensive patterns
Strategy: validation
Validate before calling
long targetPos = computedOffset; // whatever the caller computed
long fileLen = fs.getFileStatus(path).getLen();
if (targetPos < 0 || targetPos > fileLen) {
throw new IllegalArgumentException(
"seek target " + targetPos + " outside [0, " + fileLen + "] for " + path);
}
in.seek(targetPos); Try / catch
try {
in.seek(targetPos);
} catch (EOFException e) {
// negative or past-EOF target: programming error in offset math - fail loudly, do not retry
throw new IllegalArgumentException("bad seek offset " + targetPos, e);
} Prevention
- Derive every seek offset with Math.max(0, ...) when it comes from a subtraction.
- Validate offsets parsed from index/ footer metadata before use.
- Unit-test boundary offsets 0, 1, and fileLen.
- Remember skip() clamps but seek() does not - never feed seek() raw computed negatives.
When it happens
Trigger: Calling fsDataInputStream.seek(n) with n negative, e.g. seek(getPos() - delta) where delta > getPos(), or seek(-1). It is NOT produced by skip(): skip() clamps positive n to the file length before delegating to seek(), so only direct seek() calls with an under-flowing computed offset hit it.
Common situations: Record readers that compute a previous-record start as (currentPos - recordLength) and underflow at the first record; offsets parsed from corrupted index/footer metadata; index rebuild tools that subtract a header size larger than the current position; ported code that assumed skip()/seek() silently accept negative values.
Related errors
- Negative Position
- Stream is closed!
- BlockReader failed to seek to {}. Instead, it seeked to {}.
- Mark/reset not supported
- can't read a negative number of bytes.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/90831947e1c35a99.
Report an issue: GitHub.