oracle/graal · error · IllegalArgumentException
Expected an espresso constant got a {}
Error message
Expected an espresso constant got a {} What it means
EspressoExternalSnippetReflectionProvider.asObject(type, constant) converts guest Espresso constants to host objects, but only accepts EspressoExternalObjectConstant instances. Passing a constant produced by a different JVMCI constant provider (e.g. the host HotSpot provider) violates that boundary and throws IllegalArgumentException. The narrow surface is intentional: only guest strings and byte arrays can be materialized on the host.
Source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalSnippetReflectionProvider.java:86
return new EspressoExternalObjectConstant(access, guestArray);
}
throw JVMCIError.shouldNotReachHere("Cannot create JavaConstant for external JVMCI: " + clazz + ". Only primitive arrays are supported.");
}
/**
* Converts selected guest constants to host objects.
* <p>
* This conversion is intentionally narrow: strings and byte arrays are supported for
* compatibility, while arbitrary guest objects are rejected.
*/
@Override
@SuppressWarnings("unchecked")
public <T> T asObject(Class<T> type, JavaConstant constant) {
if (constant.isNull() || !constant.getJavaKind().isObject()) {
return null;
}
if ((!(constant instanceof EspressoExternalObjectConstant objConstant))) {
throw new IllegalArgumentException("Expected an espresso constant got a " + safeGetClass(constant));
}
Value value = objConstant.getValue();
Value metaObject = value.getMetaObject();
if (access.java_lang_String_class.equals(metaObject)) {
if (!type.isAssignableFrom(String.class)) {
return null;
}
return (T) value.asString();
}
if (access.byte_array_class.equals(metaObject)) {
if (!type.isAssignableFrom(byte[].class)) {
return null;
}
int size = Math.toIntExact(value.getArraySize());
byte[] result = new byte[size];
access.invokeJVMCIHelper("copyByteArray", value, result);
return (T) result;
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Ensure the JavaConstant was produced by the same EspressoExternalVMAccess/constant reflection provider instance you are reflecting with.
- Check constant instanceof EspressoExternalObjectConstant before calling asObject, and skip/handle foreign constants separately.
- If you need host-object reflection, use the host snippet reflection provider for host constants instead of the Espresso one.
Example fix
// before
String s = snippetReflection.asObject(String.class, constant);
// after
if (constant instanceof EspressoExternalObjectConstant esc) {
String s = snippetReflection.asObject(String.class, constant);
} else {
String s = hostSnippetReflection.asObject(String.class, constant);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!(constant instanceof EspressoExternalObjectConstant)) {
// constant is host or foreign; use the host snippet reflection instead
} Type guard
static boolean isEspressoConstant(JavaConstant c) {
return c instanceof EspressoExternalObjectConstant;
} Try / catch
catch (IllegalArgumentException e) when message starts with 'Expected an espresso constant' -> fall back to host snippet reflection; do not swallow silently.
Prevention
- Keep one snippet reflection per provider and pass constants only to their own provider.
- Centralize constant-to-host conversion behind a dispatcher that checks instanceof first.
- In multi-context setups, tag constants with their context.
When it happens
Trigger: Calling snippetReflection.asObject(String.class, c) where c came from another provider (HotSpotConstantReflectionProvider, a different Espresso context, or JavaConstant.forObject on a host object); also non-object kinds filtered earlier return null, but wrong-provider object constants throw here.
Common situations: Mixing host-compiled constants with Espresso guest constants in a Graal snippet substitution; multi-context setups where two Espresso VMs each produce constants and the wrong snippet reflection is used; upgrading code that previously passed raw host objects.
Related errors
- Constant has unexpected type {}: {}
- Invalid component type
- Element {} should be an espresso object constant, got {}
- Expected an EspressoExternalObjectConstant, got {}
- Expected an EspressoExternalObjectConstant for src, got {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/2620386d02943756.
Report an issue: GitHub.