oracle/graal · error · IllegalArgumentException
Invalid output range: {}..{} for array of length {}
Error message
Invalid output range: {}..{} for array of length {} What it means
After validating the source range, copyMemory checks that the destination byte[] can hold bytesToCopy = srcTo - srcFrom starting at dstFrom. This IllegalArgumentException fires when dstFrom is negative or dstFrom + bytesToCopy would run past dst.length — the destination slice is too small for the requested bytes.
Source
Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:499
@Override
public void copyMemory(JavaConstant src, int srcFrom, int srcTo, byte[] dst, int dstFrom) {
ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(src);
if (arrayType == null || !arrayType.isArray() || !arrayType.getComponentType().isPrimitive()) {
throw new IllegalArgumentException("Expected a primitive array constant, got " + src);
}
var array = providers.getSnippetReflection().asObject(Object.class, src);
if (array == null) {
throw new IllegalArgumentException("Could not unwrap an array constant: " + src);
}
int sourceArrayEnd = Array.getLength(array) * arrayType.getComponentType().getJavaKind().getByteCount();
if (srcFrom < 0 || srcTo > sourceArrayEnd || srcTo < srcFrom) {
throw new IllegalArgumentException(
"Invalid input range: " + srcFrom + ".." + srcTo + " for array of length " + Array.getLength(array) + " with kind " + arrayType.getComponentType().getJavaKind());
}
int bytesToCopy = srcTo - srcFrom;
if (dstFrom < 0 || dstFrom > dst.length - bytesToCopy) {
throw new IllegalArgumentException("Invalid output range: " + dstFrom + ".." + (dstFrom + bytesToCopy) + " for array of length " + dst.length);
}
var unsafe = Unsafe.getUnsafe();
unsafe.copyMemory(array, unsafe.arrayBaseOffset(array.getClass()) + srcFrom, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET + dstFrom, bytesToCopy);
}
/**
* Host mode performs the unaligned read with {@link Unsafe} against the unwrapped hosted array
* object.
*/
@Override
public JavaConstant readPrimitiveArrayUnaligned(JavaConstant primitiveArray, JavaKind kind, int offset) {
if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {
throw new IllegalArgumentException("Expected a non-void primitive kind, got " + kind);
}
ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(primitiveArray);
if (arrayType == null || !arrayType.isArray() || !arrayType.getComponentType().isPrimitive()) {
throw new IllegalArgumentException("Expected a primitive array constant, got " + primitiveArray);
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Allocate dst with at least (srcTo - srcFrom) bytes and use dstFrom = 0, or verify dst.length - dstFrom >= srcTo - srcFrom before the call
- Derive the buffer size from the component kind's byte count, not the element count
- Write a small guard that clamps or rejects the copy when the destination is too small
Example fix
// before byte[] dst = new byte[4]; // but src is long[1] => 8 bytes vmAccess.copyMemory(srcConst, 0, 8, dst, 0); // after int bytes = srcTo - srcFrom; byte[] dst = new byte[bytes]; vmAccess.copyMemory(srcConst, srcFrom, srcTo, dst, 0);
Defensive patterns
Strategy: validation
Validate before calling
int bytes = srcTo - srcFrom;
if (dst == null || dstFrom < 0 || dst.length - dstFrom < bytes) {
dst = new byte[bytes]; dstFrom = 0; // or reject
} Prevention
- Size destination buffers from byte counts, never element counts
- Allocate dst exactly (srcTo - srcFrom) when you control the call
- Keep one shared bounds-check helper for src and dst ranges
When it happens
Trigger: Calling copyMemory with a dst byte[] shorter than srcTo - srcFrom, or a dstFrom that leaves insufficient room: dst = new byte[4] while copying 8 bytes from a long[]; or dstFrom near the end of a larger buffer.
Common situations: Sizing the output buffer from element count instead of byte count; reusing a fixed-size scratch buffer across arrays of different kinds; forgetting that dstFrom shifts the window.
Related errors
- Invalid input range: {}..{} for array of length {} with kind
- Could not unwrap an array constant: {}
- Element {} should be a {}, got {}
- Element {} should be an object, got {}
- Expected an array constant, got {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/da082a55f5202689.
Report an issue: GitHub.