oracle/graal · error · IllegalArgumentException
Expected an espresso object receiver, got {}
Error message
Expected an espresso object receiver, got {} What it means
Thrown by EspressoExternalResolvedJavaField.writeValue when writing an instance field: the receiver JavaConstant passed by the JVMCI caller is not an EspressoExternalObjectConstant. The external vmaccess layer can only forward receivers that were created by the same Espresso VM access instance (they wrap a guest polyglot Value); any other JavaConstant implementation (e.g. a host HotSpot-compatible constant or a primitive constant) has no guest Value to pass to the guest field write and is rejected. The message names the offending constant's class so you can trace where the foreign constant came from.
Source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaField.java:132
if (value == null) {
throw new NullPointerException("value");
}
final Value receiverValue;
if (isStatic()) {
if (receiver != null) {
throw new IllegalArgumentException("Static field write requires null receiver");
}
receiverValue = null;
} else {
if (receiver == null) {
throw new NullPointerException("receiver");
}
if (receiver.isNull()) {
throw new IllegalArgumentException("Receiver is null");
}
if (!(receiver instanceof EspressoExternalObjectConstant espressoReceiver)) {
throw new IllegalArgumentException("Expected an espresso object receiver, got " + receiver.getClass().getName());
}
receiverValue = espressoReceiver.getValue();
}
JavaKind kind = getJavaKind();
final Object boxed;
if (kind == JavaKind.Object) {
if (value.isNull()) {
boxed = null;
} else if (value instanceof EspressoExternalObjectConstant objConst) {
boxed = objConst.getValue();
} else {
throw new IllegalArgumentException("Expected an espresso object constant, got " + value.getClass().getName());
}
} else {
if (kind != value.getJavaKind()) {
throw new IllegalArgumentException("Expected value kind " + kind + " but got " + value.getJavaKind());
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Source every receiver constant from the same Espresso VM access (EspressoExternalConstantReflectionProvider / EspressoExternalSnippetReflectionProvider.asJavaConstant) so it is an EspressoExternalObjectConstant
- Check receiver.getClass().getName() in the error and find the provider that created it; replace that provider with the Espresso one for guest objects
- If you must bridge a host object, first map it into the guest (e.g. asForeign/polyglot Value) and then wrap it via the Espresso snippet/constant reflection before writing the field
Example fix
// before: receiver came from host JVMCI field.writeValue(hostReceiverConstant, valueConstant); // after: obtain the receiver from the Espresso vmaccess layer JavaConstant espressoReceiver = espressoAccess.getSnippetReflection().asJavaConstant(guestObject); field.writeValue(espressoReceiver, valueConstant);
Defensive patterns
Strategy: type-guard
Validate before calling
// before writing an instance field
if (!field.isStatic() && !(receiver instanceof EspressoExternalObjectConstant)) {
throw new IllegalStateException("receiver not from Espresso vmaccess: " + receiver.getClass());
} Prevention
- Source all receiver/value constants from one EspressoExternalVMAccess instance; never mix constants across JVMCI backends
- In debug builds assert constant provenance (class name) before every field write
- Wrap field writes in a helper that takes the guest polyglot Value and does the constant wrapping internally
When it happens
Trigger: Calling ResolvedJavaField write/setValue on an instance field obtained from EspressoExternalVMAccess with a receiver constant produced by a different JVMCI backend (HotSpotConstantReflectionProvider, aSnippetReflection of the host, or a hand-rolled JavaConstant). Also happens when tooling re-wraps constants between a host compiler context and the Espresso guest context.
Common situations: Mixing JVMCI meta objects from two JVMCI runtimes in one compiler pipeline (e.g. libgraal-style vmaccess adapter pointed at Espresso while the rest of the pipeline still uses host JVMCI constants); unit tests that fabricate mock JavaConstant receivers; version upgrades where a ConstantReflectionProvider implementation changed which constant class it returns.
Related errors
- Expected an espresso object constant, got {}
- Bad argument kind at index {}: expected Object, got {} wrapp
- Expected value kind {} but got {}
- Bad receiver: expected Object, got {}
- Constant has unexpected type {}: {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/086e0875e94577f1.
Report an issue: GitHub.