oracle/graal · error · IllegalArgumentException

Expected an EspressoExternalResolvedJavaField, got {}

Error message

Expected an EspressoExternalResolvedJavaField, got {}

What it means

EspressoExternalVMAccess.writeField(field, receiver, value) requires an EspressoExternalResolvedJavaField because only that class exposes the guest field Value needed to perform the reflective store. Passing a field implementation from another JVMCI backend makes the write impossible, so it fails fast with IllegalArgumentException instead of silently writing to the wrong target.

Source

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

    }

    @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();
        Value array;
        boolean isPrimitiveArray;
        int dimensions = arrayType.getDimensions();
        if (elementalType instanceof EspressoExternalResolvedInstanceType elementalInstanceType) {
            array = invokeJVMCIHelper("newObjectArray", elementalInstanceType.getMetaObject(), dimensions, elements.length);
            isPrimitiveArray = false;
        } else {
            JavaKind javaKind = elementalType.getJavaKind();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Resolve the field on an Espresso-resolved type so you get an EspressoExternalResolvedJavaField.
  2. Check field instanceof EspressoExternalResolvedJavaField (or owns(field)) before writing; use the owning provider otherwise.
  3. Avoid mocking ResolvedJavaField in tests; use the real Espresso meta access.

Example fix

// before
vmAccess.writeField(field, receiver, value);

// after
if (vmAccess.owns(field)) {
    vmAccess.writeField(field, receiver, value);
} else {
    foreignAccess.writeField(field, receiver, value);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(field instanceof EspressoExternalResolvedJavaField)) {
    // route to the owning provider's write path
}

Type guard

static boolean isEspressoField(ResolvedJavaField f) {
    return f instanceof EspressoExternalResolvedJavaField;
}

Try / catch

catch (IllegalArgumentException e) with 'Expected an EspressoExternalResolvedJavaField' -> re-resolve the field on the Espresso type and retry.

Prevention

When it happens

Trigger: Calling vmAccess.writeField() with a ResolvedJavaField resolved through the host HotSpot provider or a hand-rolled/stub field object.

Common situations: Snippet parameter patching and foreign-object initialization that mix providers; test doubles implementing ResolvedJavaField; cross-context field writes in polyglot embeddings.

Related errors


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