oracle/graal · error · IllegalArgumentException

Expected an EspressoExternalResolvedJavaMethod, got {}

Error message

Expected an EspressoExternalResolvedJavaMethod, got {}

What it means

EspressoExternalVMAccess.invoke(method, receiver, args) can only execute methods it owns — those represented by EspressoExternalResolvedJavaMethod, which carry a guest Truffle Value that can be reflectively invoked. Any other ResolvedJavaMethod implementation (HotSpot-based, proxy, or from another context) has no guest Value, so the call is rejected with IllegalArgumentException before any execution is attempted.

Source

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

    @Override
    public boolean owns(ResolvedJavaType value) {
        return value instanceof Element;
    }

    @Override
    public boolean owns(ResolvedJavaMethod value) {
        return value instanceof Element;
    }

    @Override
    public boolean owns(ResolvedJavaField value) {
        return value instanceof Element;
    }

    @Override
    public JavaConstant invoke(ResolvedJavaMethod method, JavaConstant receiver, JavaConstant... arguments) {
        if (!(method instanceof EspressoExternalResolvedJavaMethod espressoMethod)) {
            throw new IllegalArgumentException("Expected an EspressoExternalResolvedJavaMethod, got " + safeGetClass(method));
        }
        return espressoMethod.invoke(receiver, arguments);
    }

    @Override
    public void writeField(ResolvedJavaField field, JavaConstant receiver, JavaConstant value) {
        if (!(field instanceof EspressoExternalResolvedJavaField espressoField)) {
            throw new IllegalArgumentException("Expected an EspressoExternalResolvedJavaField, got " + safeGetClass(field));
        }
        espressoField.writeValue(receiver, value);
    }

    @Override
    public JavaConstant asArrayConstant(ResolvedJavaType componentType, JavaConstant... elements) {
        if (!(componentType.getArrayClass() instanceof EspressoExternalResolvedArrayType arrayType)) {
            throw new IllegalArgumentException("Invalid component type");
        }
        EspressoResolvedJavaType elementalType = arrayType.getElementalType();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Resolve the method through this Espresso provider (lookupMethod / resolve on Espresso types) before invoking.
  2. Guard with method instanceof EspressoExternalResolvedJavaMethod (or owns(method)) and route foreign methods to their own invocation path.
  3. In tests, build methods via the Espresso external meta access rather than mocking the interface.

Example fix

// before
JavaConstant r = vmAccess.invoke(method, receiver, args);

// after
if (vmAccess.owns(method)) {
    JavaConstant r = vmAccess.invoke(method, receiver, args);
} else {
    JavaConstant r = foreignInvoke(method, receiver, args);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(method instanceof EspressoExternalResolvedJavaMethod)) {
    // re-resolve via this provider or route to foreign invocation
}

Type guard

static boolean isEspressoMethod(ResolvedJavaMethod m) {
    return m instanceof EspressoExternalResolvedJavaMethod;
}

Try / catch

catch (IllegalArgumentException e) with 'Expected an EspressoExternalResolvedJavaMethod' -> re-resolve the method through Espresso meta access and retry once.

Prevention

When it happens

Trigger: Calling vmAccess.invoke() with a ResolvedJavaMethod obtained from host HotSpot meta access, a mocking/stub implementation, or a second Espresso context's provider.

Common situations: Foreign-call setup in substitutions that resolves methods via the wrong MetaAccessProvider; test harnesses that pass mocked ResolvedJavaMethod objects; refactors that share method handles across contexts.

Related errors


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