apache/hadoop · error · EOFException
Negative Position
Error message
Negative Position
What it means
ByteRangeInputStream.seek() deliberately does not validate the position; it just records startPos/currentPos and marks the stream SEEK. The check happens lazily on the next read, when openInputStream(startPos) throws EOFException for any negative offset. So this error means seek(negative) (or an equivalent state) was followed by a read on a WebHDFS input stream.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/web/ByteRangeInputStream.java:133
if (in != null) {
in.close();
}
InputStreamAndFileLength fin = openInputStream(startPos);
in = fin.in;
fileLength = fin.length;
status = StreamStatus.NORMAL;
break;
case CLOSED:
throw new IOException("Stream closed");
}
return in;
}
@VisibleForTesting
protected InputStreamAndFileLength openInputStream(long startOffset)
throws IOException {
if (startOffset < 0) {
throw new EOFException("Negative Position");
}
// Use the original url if no resolved url exists, eg. if
// it's the first time a request is made.
final boolean resolved = resolvedURL.getURL() != null;
final URLOpener opener = resolved? resolvedURL: originalURL;
final HttpURLConnection connection = opener.connect(startOffset, resolved);
resolvedURL.setURL(getResolvedUrl(connection));
InputStream in = connection.getInputStream();
final Long length;
final Map<String, List<String>> headers = connection.getHeaderFields();
if (isChunkedTransferEncoding(headers)) {
// file length is not known
length = null;
} else {
// for non-chunked transfer-encoding, get content-length
final String cl = connection.getHeaderField(HttpHeaders.CONTENT_LENGTH);View on GitHub (pinned to 2add963021)
Solutions
- Validate the offset before seeking: if (pos < 0) throw/fallback — positions are non-negative by contract
- Fix the arithmetic: when reading backwards, clamp to 0 with Math.max(0, getPos() - n)
- Treat -1 from any matcher/index API as 'not found' and never feed it to seek()
Example fix
// before
long pos = Math.max(0, in.getPos() - tailLen);
in.seek(pos);
// after
long pos = in.getPos() - tailLen;
if (pos < 0) {
throw new IllegalArgumentException("seek offset " + pos + " is negative");
}
in.seek(pos); Defensive patterns
Strategy: validation
Validate before calling
if (targetPos < 0) {
throw new IllegalArgumentException("seek position must be >= 0, got " + targetPos);
}
in.seek(targetPos); Try / catch
try {
in.seek(pos); in.read(buf);
} catch (EOFException e) {
if ("Negative Position".equals(e.getMessage())) {
throw new IllegalArgumentException("computed a negative seek offset: " + pos, e);
}
throw e;
} Prevention
- Clamp backward offsets: Math.max(0, getPos() - n)
- Never pass matcher/index results (-1 = not found) into seek()
- Note seek() itself never throws this — it always surfaces on the NEXT read, so validate eagerly
When it happens
Trigger: Call seek(p) with p < 0 on a WebHDFS FSDataInputStream, then read — e.g., computing an offset with getPos() - n where n exceeds the current position, or seeding a seek from an uninitialized -1 variable.
Common situations: Offset arithmetic that underflows near the start of the file (reading the last N bytes of a prefix), passing -1 sentinels from parsers/regex match results into seek, or position values derived from user input without validation.
Related errors
- Cannot seek to negative offset
- Stream closed
- ${className} does not support seek.
- ${className} does not support seekToNewSource.
- Cannot seek to a negative offset
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/ac38137a7309d302.
Report an issue: GitHub.