oracle/graal · error · IllegalArgumentException

Constant has unexpected type {}: {}

Error message

Constant has unexpected type {}: {}

What it means

EspressoExternalVMAccess.getModule(type) mirrors java.lang.Class.getModule inside the guest Espresso VM and wraps the returned module in a EspressoExternalResolvedJavaModule. If the constant reflection layer returns a JavaConstant that is not an EspressoExternalObjectConstant (i.e. it originated from a foreign JVMCI backend), the wrapper cannot extract the guest Value and throws IllegalArgumentException.

Source

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

        return lookupType(name, systemClassLoader);
    }

    @Override
    public ResolvedJavaType lookupPlatformClassLoaderType(String name) {
        return lookupType(name, platformClassLoader);
    }

    @Override
    public ResolvedJavaType lookupBootClassLoaderType(String name) {
        return lookupType(name, JavaConstant.NULL_POINTER);
    }

    @Override
    public ResolvedJavaModule getModule(ResolvedJavaType type) {
        JavaConstant originalClass = providers.getConstantReflection().asJavaClass(type);
        JavaConstant module = invoke(java_lang_Class_getModule, originalClass);
        if (!(module instanceof EspressoExternalObjectConstant espressoConstant)) {
            throw new IllegalArgumentException("Constant has unexpected type " + module.getClass() + ": " + module);
        }
        Value value = espressoConstant.getValue();
        return new EspressoExternalResolvedJavaModule(this, value);
    }

    @Override
    public ResolvedJavaPackage getPackage(ResolvedJavaType type) {
        JavaConstant originalClass = providers.getConstantReflection().asJavaClass(type);
        JavaConstant pkg = invoke(java_lang_Class_getPackage, originalClass);
        if (!(pkg instanceof EspressoExternalObjectConstant espressoConstant)) {
            throw new IllegalArgumentException("Constant has unexpected type " + pkg.getClass() + ": " + pkg);
        }
        Value value = espressoConstant.getValue();
        return new EspressoExternalResolvedJavaPackage(this, value);
    }

    @Override
    public ResolvedJavaModuleLayer bootModuleLayer() {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Only call getModule() on ResolvedJavaType instances created by the same EspressoExternalVMAccess (check vmAccess.owns(type) if available).
  2. Route types from other providers through their own module accessor instead.
  3. Ensure the constant reflection provider in providers is the Espresso one, not a delegating host provider.

Example fix

// before
ResolvedJavaModule m = vmAccess.getModule(someType);

// after
if (vmAccess.owns(someType)) {
    ResolvedJavaModule m = vmAccess.getModule(someType);
} else {
    ResolvedJavaModule m = otherProvider.getModule(someType);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!vmAccess.owns(type)) {
    // resolve module via the type's own provider instead
}

Type guard

static boolean ownsType(EspressoExternalVMAccess access, ResolvedJavaType t) {
    return access.owns(t);
}

Try / catch

catch (IllegalArgumentException e) { log foreign type and rethrow — mixing providers here usually indicates a design bug, not a runtime condition. }

Prevention

When it happens

Trigger: Passing a ResolvedJavaType from a different JVMCI provider (HotSpot resolved type, or a type from another Espresso context) to getModule(); the intermediate asJavaClass/invoke then yields a foreign constant that fails the instanceof EspressoExternalObjectConstant check.

Common situations: Compiler plugins or substitutions that mix host and guest meta-access providers; polyglot embeddings with multiple Espresso contexts; refactors that route types through the wrong providers instance.

Related errors


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