{"record":{"id":"3632b86aeb316216","repo":"juicedata/juicefs","slug":"arguments-off-len","errorCode":null,"errorMessage":"arguments: \" + off + \" \" + len","messagePattern":"arguments: \" \\+ off \\+ \" \" \\+ len","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java","lineNumber":1134,"sourceCode":"    }\n\n    private boolean refill() throws IOException {\n      buf.clear();\n      int read = read(position, buf);\n      if (read <= 0) {\n        buf.limit(0);\n        return false; // EOF\n      }\n      buf.position(0);\n      buf.limit(read);\n      position += read;\n      return true;\n    }\n\n    @Override\n    public synchronized int read(long pos, byte[] b, int off, int len) throws IOException {\n      if (b == null || off < 0 || len < 0 || b.length - off < len) {\n        throw new IllegalArgumentException(\"arguments: \" + off + \" \" + len);\n      }\n      int got = read(pos, ByteBuffer.wrap(b, off, len));\n      statistics.incrementBytesRead(got);\n      return got;\n    }\n\n    @Override\n    public synchronized int read(ByteBuffer b) throws IOException {\n      if (!b.hasRemaining())\n        return 0;\n      if (buf == null)\n        throw new IOException(\"stream was closed\");\n      if (!buf.hasRemaining() && b.remaining() <= buf.capacity() && !refill()) {\n        return -1;\n      }\n      ByteBuffer srcBuf = buf.duplicate();\n      int got = Math.min(b.remaining(), srcBuf.remaining());\n      if (got > 0) {","sourceCodeStart":1116,"sourceCodeEnd":1152,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/java/src/main/java/io/juicefs/JuiceFileSystemImpl.java#L1116-L1152","documentation":"The positioned read read(long pos, byte[] b, int off, int len) throws IllegalArgumentException(\"arguments: off len\") when b is null, off < 0, len < 0, or b.length - off < len. These mirror the java.io APIs' preconditions: the requested range must fit inside the caller-supplied buffer. The message includes the offending off and len values.","triggerScenarios":"Calling in.read(pos, b, off, len) with a null buffer, negative off/len, or a (off + len) pair exceeding b.length — commonly a len computed as bufferCapacity while the actual array is smaller, or off/len swapped.","commonSituations":"Preallocated-buffer pooling code passing a capacity constant instead of the array's real length; off-by-one on off; reading with a length derived from metadata larger than the allocated buffer.","solutions":["Validate before calling: assert off >= 0, len >= 0, and off + len <= b.length.","Pass b.length-derived values: use off=0, len=b.length for full-buffer reads.","Fix swapped parameters if off and len are transposed at the call site."],"exampleFix":"// before\nin.read(pos, buf, off, bufSize); // buf may be smaller than bufSize\n// after\nlong n = Math.min(bufSize, buf.length - off);\nin.read(pos, buf, off, (int) n);","handlingStrategy":"validation","validationCode":"if (b == null || off < 0 || len < 0 || b.length - off < len) {\n  throw new IllegalArgumentException(\"bad read args off=\" + off + \" len=\" + len + \" buf=\" + (b == null ? \"null\" : b.length));\n}\nint got = in.read(pos, b, off, len);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive len from b.length and off, not from an unrelated capacity constant.","Keep off/len parameter order straight at call sites.","Assert buffer invariants in unit tests for any custom read wrapper."],"tags":["java","hadoop","argument-validation","pread"],"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-14T05:17:10.506Z"}