juicedata/juicefs · warning · EOFException
Unable to skip %s bytes (position=%s, fileSize=%s): %s
Error message
Unable to skip %s bytes (position=%s, fileSize=%s): %s
What it means
This EOFException is thrown by FileInputStream.skipNBytes in JuiceFileSystemImpl when the requested skip would advance the read position past the end of the file. The library tracks the current position and the file length captured at open(); if position + n exceeds fileLen, the skip is impossible, so it fails instead of silently clamping (unlike skip(), which clamps). The message reports the requested byte count, current position, file size, and the resulting target offset.
Source
Thrown at sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java:1213
} else {
buf.position(0);
buf.limit(0);
position = p;
}
}
public synchronized void skipNBytes(long n) throws IOException {
if (buf == null) {
throw new IOException("stream was closed");
}
if (n <= 0) {
return;
}
long np = position + n;
if (np > fileLen) {
throw new EOFException(String.format("Unable to skip %s bytes (position=%s, fileSize=%s): %s", n, position, fileLen, np));
}
position = np;
}
@Override
public synchronized long skip(long n) throws IOException {
if (n < 0)
return -1;
if (buf == null)
throw new IOException("stream was closed");
long pos = getPos();
if (pos + n > fileLen) {
n = fileLen - pos;
}
seek(pos + n);
return n;
}
@OverrideView on GitHub (pinned to c9a67b23e8)
Solutions
- Catch EOFException around skipNBytes and treat it as end-of-data (it is the documented signal that the file end was reached).
- Reopen the file and re-fetch its length before computing skip offsets if the file may be modified concurrently.
- Use skip(n) instead of skipNBytes(n) if you want clamping-to-EOF semantics rather than an exception.
- Verify the caller's expected record/split lengths against the actual file size (fs.getFileStatus(path).getLen()) before skipping.
Example fix
// before
in.skipNBytes(remaining); // throws EOFException near EOF
// after
try {
in.skipNBytes(remaining);
} catch (EOFException e) {
// reached end of file earlier than expected; stop reading
break;
} Defensive patterns
Strategy: try-catch
Validate before calling
long fileLen = fs.getFileStatus(path).getLen();
long pos = in.getPos();
if (pos + n > fileLen) {
throw new EOFException("skip would pass EOF: pos=" + pos + " n=" + n + " len=" + fileLen);
}
in.skipNBytes(n); Try / catch
try {
in.skipNBytes(n);
} catch (EOFException e) {
// end-of-file reached; handle as normal termination
LOG.warn("skip hit EOF: {}", e.getMessage());
} Prevention
- Re-check file length (getFileStatus) before large skips on files that may change.
- Prefer skip(n) when clamping to EOF is acceptable behavior.
- Compute skip offsets from the stream's own getPos(), not stale listing metadata.
- Treat EOFException from skipNBytes as an expected signal, not a crash.
When it happens
Trigger: Calling FSDataInputStream.skipNBytes(n) (directly or via the FileSystem API) where position + n > fileLen — e.g. skipping past EOF after reading near the end of a truncated or concurrently-shrinking file, or using a stale file length.
Common situations: Spark/MapReduce record readers trusting a stale split length while the file was truncated or overwritten between listing and read; application logic computing skip offsets from a different (larger) file version; using skipNBytes with a length taken from a directory listing that has since changed.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- write
- failed to read segment type: %v
- failed to read segment %s length: %v
- Invalid start or len parameter
- stream was closed
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/e56ca174c9032cc4.
Report an issue: GitHub.