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;
    }

    @Override

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Catch EOFException around skipNBytes and treat it as end-of-data (it is the documented signal that the file end was reached).
  2. Reopen the file and re-fetch its length before computing skip offsets if the file may be modified concurrently.
  3. Use skip(n) instead of skipNBytes(n) if you want clamping-to-EOF semantics rather than an exception.
  4. 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

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


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/e56ca174c9032cc4. Report an issue: GitHub.