{"record":{"id":"9dd6d701ea1ce1c2","repo":"juicedata/juicefs","slug":"invalid-start-or-len-parameter","errorCode":null,"errorMessage":"Invalid start or len parameter","messagePattern":"Invalid start or len parameter","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java","lineNumber":1013,"sourceCode":"    if (file == null) {\n      return null;\n    }\n    if (needCheckPermission() && !checkPathAccess(file.getPath(), FsAction.READ, \"getFileBlockLocations\")) {\n      return superGroupFileSystem.getFileBlockLocations(file, start, len);\n    }\n\n    if (isEmpty(discoverNodesUrl) || cacheReplica <= 0) {\n      BlockLocation[] bls = super.getFileBlockLocations(file, start, len);\n      if (bls != null) {\n        for (BlockLocation bl : bls) {\n          setStorageId(bl);\n        }\n      }\n      return bls;\n    }\n\n    if (start < 0 || len < 0) {\n      throw new IllegalArgumentException(\"Invalid start or len parameter\");\n    }\n    if (file.getLen() <= start) {\n      return new BlockLocation[0];\n    }\n    if (cacheReplica <= 0) {\n      String[] name = new String[]{\"localhost:50010\"};\n      String[] host = new String[]{\"localhost\"};\n      return new BlockLocation[]{new BlockLocation(name, host, 0L, file.getLen())};\n    }\n    BgTaskUtil.putTask(name, \"Node fetcher\", this::initCache, 10, 10, TimeUnit.MINUTES);\n    if (file.getLen() <= start + len) {\n      len = file.getLen() - start;\n    }\n    long code = normalizePath(file.getPath()).hashCode();\n    BlockLocation[] locs = new BlockLocation[(int) (len / blocksize) + 2];\n    int indx = 0;\n    while (len > 0) {\n      long blen = len < blocksize ? len : blocksize - start % blocksize;","sourceCodeStart":995,"sourceCodeEnd":1031,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java#L995-L1031","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Clamp start and len before calling: if (start < 0) start = 0; if (len < 0) len = 0.","Fix the split-computation code so start/len are derived from non-negative values (guard against integer underflow/overflow).","If the negative value comes from persisted split metadata, regenerate or revalidate the job's input splits."],"exampleFix":"// before\nBlockLocation[] locs = fs.getFileBlockLocations(status, split.getStart() - pad, split.getLength());\n// after\nlong start = Math.max(0, split.getStart() - pad);\nlong len = Math.max(0, split.getLength());\nBlockLocation[] locs = fs.getFileBlockLocations(status, start, len);","handlingStrategy":"validation","validationCode":"if (start < 0 || len < 0) {\n  start = Math.max(0, start);\n  len = Math.max(0, len);\n}\nBlockLocation[] locs = fs.getFileBlockLocations(status, start, len);","typeGuard":null,"tryCatchPattern":"try {\n  locations = fs.getFileBlockLocations(status, start, len);\n} catch (IllegalArgumentException e) {\n  LOG.warn(\"bad start/len for {}: {}\", status.getPath(), e.getMessage());\n  locations = new BlockLocation[0];\n}","preventionTips":["Always clamp split offsets/lengths to >= 0 before querying block locations.","Check arithmetic that subtracts padding from offsets for underflow.","Add unit tests for split computations at offset 0 and file end."],"tags":["java","hadoop","argument-validation","block-locations"],"backgroundTag":"invalid-argument-value","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}