apache/hadoop · error · EOFException
Cannot seek to a negative offset
Error message
Cannot seek to a negative offset
What it means
CryptoInputStream.seek(pos) validates pos >= 0 first and throws EOFException with FSExceptionMessages.NEGATIVE_SEEK ("Cannot seek to a negative offset") for negative positions. This is a caller-input error independent of wrapped-stream capabilities; Hadoop filesystem code deliberately uses EOFException for negative seeks, which can mislead readers expecting IllegalArgumentException.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java:526
+ " does not support positioned readFully.");
}
((PositionedReadable) in).readFully(position, buffer, offset, length);
if (length > 0) {
// This operation does not change the current offset of the file
decrypt(position, buffer, offset, length);
}
}
@Override
public void readFully(long position, byte[] buffer) throws IOException {
readFully(position, buffer, 0, buffer.length);
}
/** Seek to a position. */
@Override
public void seek(long pos) throws IOException {
if (pos < 0) {
throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);
}
checkStream();
/*
* If data of target pos in the underlying stream has already been read
* and decrypted in outBuffer, we just need to re-position outBuffer.
*/
if (pos <= streamOffset && pos >= (streamOffset - outBuffer.remaining())) {
int forward = (int) (pos - (streamOffset - outBuffer.remaining()));
if (forward > 0) {
outBuffer.position(outBuffer.position() + forward);
}
} else {
if (!(in instanceof Seekable)) {
throw new UnsupportedOperationException(in.getClass().getCanonicalName()
+ " does not support seek.");
}
((Seekable) in).seek(pos);
resetStreamOffset(pos);View on GitHub (pinned to 2add963021)
Solutions
- Clamp the computed offset to >= 0 before seek: Math.max(0L, target)
- Fix the upstream arithmetic that produced the negative position (overshoot in skip/read accounting)
- If the intent was 'go back n bytes', verify getPos() >= n before computing the target
Example fix
// before long target = stream.getPos() - bytesConsumed; // can go negative stream.seek(target); // after long target = Math.max(0L, stream.getPos() - bytesConsumed); stream.seek(target);
Defensive patterns
Strategy: validation
Validate before calling
if (targetPos < 0) {
throw new IllegalArgumentException("seek offset must be >= 0, got " + targetPos);
}
in.seek(targetPos); Try / catch
try {
in.seek(pos);
} catch (EOFException e) {
if (FSExceptionMessages.NEGATIVE_SEEK.equals(e.getMessage())) {
throw new IllegalArgumentException("computed a negative offset: " + pos, e);
}
throw e;
} Prevention
- Clamp computed offsets with Math.max(0, value) before seek
- Validate split/index offsets for >= 0 when loading them from sidecar files
- Unit-test backward navigation logic (getPos() - n) at position 0
When it happens
Trigger: seek(-1) or any negative position, usually from upstream arithmetic: getPos() minus an overshoot, seek(pos - n) with n > pos, or negative split/index offsets read from a corrupt index file.
Common situations: Reader code computing 'current position - bytesToSkip' without clamping at 0; off-by-one loops in custom InputFormats; offsets from malformed sidecar index files.
Related errors
- ${className} does not support seek.
- ${className} does not support seekToNewSource.
- ${className} does not support positioned read.
- ${className} does not support positioned reads with byte buf
- ${className} does not support positioned readFully.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/a1656b28df0f1a04.
Report an issue: GitHub.