oracle/graal · error · IllegalArgumentException
Expected an array constant, got {}
Error message
Expected an array constant, got {} What it means
HostVMAccess.writeArrayElement first resolves the constant's type via metaAccess.lookupJavaType(array) and verifies it is an array; this IllegalArgumentException fires when the passed JavaConstant is not an array constant at all (a scalar, null, or a non-array object). It guards Array.set against an IllegalArgumentException from the reflection layer with a clearer message.
Source
Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:361
if (componentType.isPrimitive()) {
if (componentType.getJavaKind() != element.getJavaKind()) {
throw new IllegalArgumentException("Element " + element + " should be a " + componentType.getJavaKind() + ", got " + element.getJavaKind());
}
unwrappedValue = element.asBoxedPrimitive();
} else {
if (!element.getJavaKind().isObject()) {
throw new IllegalArgumentException("Element " + element + " should be an object, got " + componentType);
}
unwrappedValue = providers.getSnippetReflection().asObject(Object.class, element);
}
Array.set(array, index, unwrappedValue);
}
@Override
public void writeArrayElement(JavaConstant array, int index, JavaConstant element) {
ResolvedJavaType arrayType = getProviders().getMetaAccess().lookupJavaType(array);
if (arrayType == null || !arrayType.isArray()) {
throw new IllegalArgumentException("Expected an array constant, got " + array);
}
Object asObject = providers.getSnippetReflection().asObject(Object.class, array);
if (asObject == null) {
throw new IllegalArgumentException("Could not unwrap array: " + array);
}
doWriteArrayElement(asObject, arrayType.getComponentType(), index, element);
}
@Override
public ResolvedJavaMethod asResolvedJavaMethod(Constant constant) {
SnippetReflectionProvider snippetReflection = providers.getSnippetReflection();
Executable executable = snippetReflection.asObject(Executable.class, (JavaConstant) constant);
if (executable != null) {
return providers.getMetaAccess().lookupJavaMethod(executable);
}
return null;
}
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Check the constant before writing: resolve its type and verify type != null && type.isArray() && type.getComponentType() != null
- Fix the upstream logic so the array-write path only receives actual array constants
- If the value may legitimately be a scalar, branch to a field/store API instead of writeArrayElement
Example fix
// before
vmAccess.writeArrayElement(maybeArrayConst, idx, valueConst);
// after
ResolvedJavaType t = providers.getMetaAccess().lookupJavaType(maybeArrayConst);
if (t == null || !t.isArray()) {
throw new IllegalArgumentException("Not an array constant: " + maybeArrayConst);
}
vmAccess.writeArrayElement(maybeArrayConst, idx, valueConst); Defensive patterns
Strategy: validation
Validate before calling
ResolvedJavaType t = providers.getMetaAccess().lookupJavaType(candidate);
if (t == null || !t.isArray()) {
// not an array constant - do not call writeArrayElement
} Type guard
boolean isArrayConstant(JavaConstant c, MetaAccessProvider meta) {
ResolvedJavaType t = meta.lookupJavaType(c);
return t != null && t.isArray();
} Prevention
- Resolve the constant's type once and branch scalar vs array before dispatching
- Never pass JavaConstant.NULL_POINTER or illegal constants to array APIs
- In data-driven code, tag slots with their expected shape instead of guessing
When it happens
Trigger: Calling writeArrayElement on a constant whose ResolvedJavaType is null (e.g. JavaConstant.NULL_POINTER or an illegal/foreign constant) or whose type is a class rather than an array type (storing into what the caller believed was an array but is a plain object or a boxed primitive).
Common situations: Data-driven pipelines where a slot can hold either a scalar or an array and the array path is chosen unconditionally; passing a constant obtained from a different JVMCI runtime/backend whose types this MetaAccessProvider cannot resolve (lookupJavaType returns null).
Related errors
- Element {} should be a {}, got {}
- Element {} should be an object, got {}
- Invalid replay boolean flag
- Required replay field is null
- Unexpected architecture name ${archName}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/64af3b5247be1028.
Report an issue: GitHub.