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

  1. Check the constant before writing: resolve its type and verify type != null && type.isArray() && type.getComponentType() != null
  2. Fix the upstream logic so the array-write path only receives actual array constants
  3. 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

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


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/64af3b5247be1028. Report an issue: GitHub.