oracle/graal · error · IndexOutOfBoundsException
offset: %s, length: %s, array length: %s
Error message
offset: %s, length: %s, array length: %s
What it means
The native-backed BinaryOutput.write(byte[], int, int) validates (off | len | b.length) < 0 || b.length - off < len and throws IndexOutOfBoundsException('offset: X, length: Y, array length: Z') — the same check as OutputStream.write semantics — before touching native memory. It protects the subsequent native address writes/ByteBuffer put from out-of-range source-array access.
Source
Thrown at compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/BinaryOutput.java:587
* Returns an address of an off-heap memory segment containing the marshalled data.
*/
public CCharPointer getAddress() {
checkClosed();
return address;
}
@Override
public void write(int b) {
checkClosed();
ensureCapacity(pos + 1);
address.write(pos++, (byte) b);
}
@Override
public void write(byte[] b, int off, int len) {
checkClosed();
if ((off | len | b.length) < 0 || b.length - off < len) {
throw new IndexOutOfBoundsException("offset: " + off + ", length: " + len + ", array length: " + b.length);
}
ensureCapacity(pos + len);
if (len > BYTEBUFFER_COPY_FROM_ARRAY_THRESHOLD) {
if (byteBufferView == null) {
byteBufferView = CTypeConversion.asByteBuffer(address, length);
}
byteBufferView.position(pos);
byteBufferView.put(b, off, len);
} else {
for (int i = 0; i < len; i++) {
address.write(pos + i, b[off + i]);
}
}
pos += len;
}
@Override
public void skip(int numberOfBytes) {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Validate off/len against b.length before the call: Objects.checkFromToIndex(off, off + len, b.length).
- Derive len from the array itself when possible (len = b.length - off) instead of a separately tracked variable.
- Fix the slicing arithmetic that produced off+len > b.length.
- Add a debug assertion of (off, len, b.length) in your wrapper around the native output.
Example fix
// before nativeOut.write(b, off, len); // after Objects.checkFromToIndex(off, off + len, b.length); nativeOut.write(b, off, len);
Defensive patterns
Strategy: validation
Validate before calling
java.util.Objects.checkFromToIndex(off, off + len, b.length); nativeOut.write(b, off, len);
Try / catch
try {
nativeOut.write(b, off, len);
} catch (IndexOutOfBoundsException e) {
// message contains offset/length/array length: fix slicing at the call site
} Prevention
- Use Objects.checkFromToIndex before writes
- Derive len from the array (b.length - off) when possible
- Watch off-by-one in chunked write loops
When it happens
Trigger: Calling write with negative off or len, off+len exceeding b.length, or a null-array edge producing b.length=0 with len>0 — usually from slicing bugs at the sender of the marshalled data.
Common situations: Substring/subarray slicing where end index exceeds the array; passing len from a protocol field without validating against the actual array size; off-by-one in chunked write loops.
Related errors
- Partial character at end
- malformed input: partial character at end
- Unknown tag %d
- Len must be non negative but was %d
- String too long to encode, %s bytes
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/7d217c2d6527d0e7.
Report an issue: GitHub.