oracle/graal · error · IllegalArgumentException

Expected a non-void primitive kind, got {}

Error message

Expected a non-void primitive kind, got {}

What it means

createPrimitiveArray(kind, length) allocates a guest primitive array via a JVMCI helper that takes the kind's type character; null kinds, reference kinds (Object), and Void have no primitive array representation, so the method rejects them up front with IllegalArgumentException. Only the eight true primitive JavaKinds are accepted.

Source

Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccess.java:581

                    continue;
                }
                if (!(element instanceof EspressoExternalObjectConstant objectElement)) {
                    throw new IllegalArgumentException("Element " + i + " should be an espresso object constant, got " + safeGetClass(element));
                }
                try {
                    array.setArrayElement(i, objectElement.getValue());
                } catch (ClassCastException e) {
                    throw new IllegalArgumentException("Element " + i + " is not an instance of the component type", e);
                }
            }
        }
        return new EspressoExternalObjectConstant(this, array);
    }

    @Override
    public JavaConstant createPrimitiveArray(JavaKind kind, int length) {
        if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {
            throw new IllegalArgumentException("Expected a non-void primitive kind, got " + kind);
        }
        if (length < 0) {
            throw new NegativeArraySizeException("Negative array size: " + length);
        }
        Value array = invokeJVMCIHelper("newPrimitiveArray", (int) kind.getTypeChar(), 1, length);
        return new EspressoExternalObjectConstant(this, array);
    }

    @Override
    public JavaConstant clonePrimitiveArray(JavaConstant primitiveArray) {
        if (!(primitiveArray instanceof EspressoExternalObjectConstant objectConstant)) {
            throw new IllegalArgumentException("Expected an EspressoExternalObjectConstant, got " + safeGetClass(primitiveArray));
        }
        EspressoResolvedObjectType arrayType = objectConstant.getType();
        if (!(arrayType.isArray() && arrayType.getComponentType().isPrimitive())) {
            throw new IllegalArgumentException("Expected a primitive array constant, got " + arrayType);
        }
        Value copy = invokeJVMCIHelper("clonePrimitiveArray", objectConstant.getValue());

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Guard the call: if (kind != null && kind.isPrimitive() && kind != JavaKind.Void) before creating.
  2. Route object/reference kinds to asArrayConstant with an Object component type instead.
  3. Treat a null kind as an upstream lookup failure and fix the type resolution.

Example fix

// before
JavaConstant a = vmAccess.createPrimitiveArray(kind, n);

// after
if (kind != null && kind.isPrimitive() && kind != JavaKind.Void) {
    JavaConstant a = vmAccess.createPrimitiveArray(kind, n);
}
Defensive patterns

Strategy: validation

Validate before calling

if (kind == null || !kind.isPrimitive() || kind == JavaKind.Void) {
    // reject or route object kinds to asArrayConstant
}

Type guard

static boolean isLegalPrimitiveKind(JavaKind k) {
    return k != null && k.isPrimitive() && k != JavaKind.Void;
}

Prevention

When it happens

Trigger: Calling createPrimitiveArray with JavaKind.Object, JavaKind.Void, or a null kind — often because a kind variable was derived from a generic type or unvalidated input.

Common situations: Generic array-building helpers that pass whatever kind a ResolvedJavaType reports without checking isPrimitive(); handling Void from method return kinds; null kind from failed lookups.

Related errors


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