prestodb/presto · error · EOFException
Negative seek offset
Error message
Negative seek offset
What it means
PrestoS3InputStream.read(position, buffer, offset, length) throws EOFException with 'Negative seek offset' when a positional (pread-style) read is requested at a negative file position. Positional reads must address a valid offset within the object.
Source
Thrown at presto-hive/src/main/java/com/facebook/presto/hive/s3/PrestoS3FileSystem.java:988
this.maxAttempts = maxAttempts;
this.maxBackoffTime = requireNonNull(maxBackoffTime, "maxBackoffTime is null");
this.maxRetryTime = requireNonNull(maxRetryTime, "maxRetryTime is null");
}
@Override
public void close()
{
closed.set(true);
closeStream();
}
@Override
public int read(long position, byte[] buffer, int offset, int length)
throws IOException
{
checkClosed();
if (position < 0) {
throw new EOFException(NEGATIVE_SEEK);
}
checkPositionIndexes(offset, offset + length, buffer.length);
if (length == 0) {
return 0;
}
try {
return retry()
.maxAttempts(maxAttempts)
.exponentialBackoff(BACKOFF_MIN_SLEEP, maxBackoffTime, maxRetryTime, 2.0)
.stopOn(InterruptedException.class, UnrecoverableS3OperationException.class, EOFException.class, FileNotFoundException.class, AbortedException.class)
.onRetry(STATS::newGetObjectRetry)
.run("getS3Object", () -> {
InputStream stream;
try {
GetObjectRequest request = new GetObjectRequest(host, keyFromPath(path))
.withRange(position, (position + length) - 1);
stream = s3.getObject(request).getObjectContent();View on GitHub (pinned to 55bb57d202)
Solutions
- Fix the caller's offset computation; log and clamp position to >= 0 upstream.
- Verify file lengths used to compute back-positions (e.g. length - footerSize) are correct.
- Guard reads: if (position < 0) throw IllegalArgumentException with context instead of proceeding.
- Check for integer overflow when computing positions from int arithmetic; use long.
Example fix
// before
long pos = fileLength - footerSize; // fileLength uninitialized -> -footerSize < 0
in.read(pos, buffer, 0, len);
// after
long pos = Math.max(0, fileLength - footerSize);
if (fileLength <= 0) throw new IllegalStateException("invalid length");
in.read(pos, buffer, 0, len); Defensive patterns
Strategy: validation
Validate before calling
long safePos = position;
if (safePos < 0) {
throw new IllegalArgumentException("read position must be >= 0, got " + safePos);
} Type guard
boolean isValidRead(long position, byte[] buffer, int offset, int length) {
return position >= 0 && offset >= 0 && length >= 0 && offset + length <= buffer.length;
} Try / catch
try {
n = in.read(position, buffer, offset, length);
} catch (EOFException e) {
if (NEGATIVE_SEEK.equals(e.getMessage())) {
throw new IllegalArgumentException("negative position passed to positional read", e);
}
throw e;
} Prevention
- Validate split start/length math before issuing positional reads.
- Use long arithmetic when computing back-positions to avoid int overflow.
- Initialize all position variables; never pass possibly-negative values.
- Clamp or reject negative positions at your reader's API boundary.
When it happens
Trigger: Calling FSDataInputStream.read(position, buffer, offset, length) with position < 0, typically from a corrupted split/offset computation or an uninitialized long used as position.
Common situations: Hive/Spark split math bug (start offset underflow); reading footer/trailer by subtracting from a wrong file length; uninitialized offset variable; integer overflow wrapping negative.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/e1894f460df9a342.
Report an issue: GitHub.