apache/hadoop · error · EOFException
Cannot seek to negative offset
Error message
Cannot seek to negative offset
What it means
DFSStripedInputStream.seek(long) validates the target position before moving the read cursor of an erasure-coded HDFS file: positions past EOF and negative positions are both rejected. A negative targetPos throws EOFException('Cannot seek to negative offset') even though the stream itself is healthy — the value passed in is illegal. The striped reader shares this strictness with the replicated reader (DFSInputStream), because internal stripe buffers are indexed from the file start.
Solutions
- Clamp the computed position before seeking: Math.max(0, targetPos).
- Audit all seek call sites for underflow-prone arithmetic and unchecked indexOf()/lastIndexOf() results.
- Map sentinel values (e.g., -1 meaning 'not found') to a real decision — skip the seek or seek(0) — instead of forwarding them.
- As a safety net, catch EOFException around seek() and log-and-correct rather than failing the whole read job.
Example fix
// before long newPos = currentPos - backTrack; in.seek(newPos); // EOFException when backTrack > currentPos // after long newPos = Math.max(0, currentPos - backTrack); in.seek(newPos);
Defensive patterns
Strategy: validation
Validate before calling
if (targetPos < 0) {
throw new IllegalArgumentException(
"seek position must be >= 0, got " + targetPos);
}
if (targetPos > in.getLen()) { // also avoids 'Cannot seek after EOF'
targetPos = in.getLen();
}
in.seek(targetPos); Try / catch
try {
in.seek(targetPos);
} catch (EOFException e) {
LOG.warn("Invalid seek target {} on {} - resetting to 0", targetPos, path, e);
in.seek(0);
} Prevention
- Never feed indexOf()/lastIndexOf() results into seek() without checking for -1.
- Clamp every computed position: Math.max(0, Math.min(pos, fileLen)).
- Validate both bounds — seek() also throws 'Cannot seek after EOF' for targets past the file length.
When it happens
Trigger: Calling seek(n) with n < 0 on an FSDataInputStream opened from an EC-coded HDFS file. Typical producers: backtracking math like pos - backTrack where backTrack > pos, and passing a -1 sentinel (e.g., the result of String.indexOf()/lastIndexOf()) directly into seek().
Common situations: Custom skip/rewind logic that subtracts from the current position without clamping; index-derived offsets not checked for -1; code ported from APIs where seek wrapped around or was a no-op on bad input.
Related errors
- Cannot seek after EOF
- Not support enhanced byte buffer access.
- Stream closed
- Stream is closed!
- All negative block group IDs are used, growing into…
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/f8fc884ec9adbdb4.
Report an issue: GitHub.
Appendix: source
Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DFSStripedInputStream.java:360
}
updateReadStatistics(readStatistics, stats.getBytesRead(),
stats.isShortCircuit(), stats.getNetworkDistance());
dfsClient.updateFileSystemReadStats(stats.getNetworkDistance(),
stats.getBytesRead(), readTimeMS);
assert readStatistics.getBlockType() == BlockType.STRIPED;
dfsClient.updateFileSystemECReadStats(stats.getBytesRead());
}
/**
* 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!");
}
if (targetPos <= blockEnd) {
final long targetOffsetInBlk = getOffsetInBlockGroup(targetPos);
if (curStripeRange.include(targetOffsetInBlk)) {
int bufOffset = getStripedBufOffset(targetOffsetInBlk);
curStripeBuf.position(bufOffset);
pos = targetPos;
return;
}
}
pos = targetPos;
blockEnd = -1;
}
private int getStripedBufOffset(long offsetInBlockGroup) {View on GitHub (pinned to 2add963021)