juicedata/juicefs · error · IllegalArgumentException

Invalid start or len parameter

Error message

Invalid start or len parameter

What it means

getFileBlockLocations(FileStatus, start, len) throws IllegalArgumentException when either the start offset or the requested length is negative. JuiceFS (like HDFS) requires both to be non-negative because they describe a byte range within the file used to compute per-block locations. Note it only validates when the node-discovery cache path is active (discoverNodesUrl set and cacheReplica > 0); otherwise the parent Hadoop FileSystem implementation is used.

Source

Thrown at sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java:1013

    if (file == null) {
      return null;
    }
    if (needCheckPermission() && !checkPathAccess(file.getPath(), FsAction.READ, "getFileBlockLocations")) {
      return superGroupFileSystem.getFileBlockLocations(file, start, len);
    }

    if (isEmpty(discoverNodesUrl) || cacheReplica <= 0) {
      BlockLocation[] bls = super.getFileBlockLocations(file, start, len);
      if (bls != null) {
        for (BlockLocation bl : bls) {
          setStorageId(bl);
        }
      }
      return bls;
    }

    if (start < 0 || len < 0) {
      throw new IllegalArgumentException("Invalid start or len parameter");
    }
    if (file.getLen() <= start) {
      return new BlockLocation[0];
    }
    if (cacheReplica <= 0) {
      String[] name = new String[]{"localhost:50010"};
      String[] host = new String[]{"localhost"};
      return new BlockLocation[]{new BlockLocation(name, host, 0L, file.getLen())};
    }
    BgTaskUtil.putTask(name, "Node fetcher", this::initCache, 10, 10, TimeUnit.MINUTES);
    if (file.getLen() <= start + len) {
      len = file.getLen() - start;
    }
    long code = normalizePath(file.getPath()).hashCode();
    BlockLocation[] locs = new BlockLocation[(int) (len / blocksize) + 2];
    int indx = 0;
    while (len > 0) {
      long blen = len < blocksize ? len : blocksize - start % blocksize;

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Clamp start and len before calling: if (start < 0) start = 0; if (len < 0) len = 0.
  2. Fix the split-computation code so start/len are derived from non-negative values (guard against integer underflow/overflow).
  3. If the negative value comes from persisted split metadata, regenerate or revalidate the job's input splits.

Example fix

// before
BlockLocation[] locs = fs.getFileBlockLocations(status, split.getStart() - pad, split.getLength());
// after
long start = Math.max(0, split.getStart() - pad);
long len = Math.max(0, split.getLength());
BlockLocation[] locs = fs.getFileBlockLocations(status, start, len);
Defensive patterns

Strategy: validation

Validate before calling

if (start < 0 || len < 0) {
  start = Math.max(0, start);
  len = Math.max(0, len);
}
BlockLocation[] locs = fs.getFileBlockLocations(status, start, len);

Try / catch

try {
  locations = fs.getFileBlockLocations(status, start, len);
} catch (IllegalArgumentException e) {
  LOG.warn("bad start/len for {}: {}", status.getPath(), e.getMessage());
  locations = new BlockLocation[0];
}

Prevention

When it happens

Trigger: Calling fs.getFileBlockLocations(fileStatus, start, len) via JuiceFileSystemImpl with start < 0 or len < 0, e.g. a miscomputed split offset (offset minus padding below zero) or a mapreduce/spark input split built with negative length.

Common situations: Custom InputFormat/RecordReader code computing split offsets with unsigned/overflowed arithmetic; frameworks passing stale or corrupted split metadata; subtracting a margin from offset 0 to add locality padding.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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