oracle/graal · error · IllegalArgumentException
Invalid guest type
Error message
Invalid guest type
What it means
Thrown by EspressoExternalVMAccess.createHostProxy when the guestType argument is not usable as a proxy interface. Espresso implements host interop with Java dynamic proxies, so the guest type must be a resolved Espresso type (EspressoExternalResolvedInstanceType) and it must be an interface; a class, array, primitive, or a ResolvedJavaType coming from a different compiler backend is rejected with IllegalArgumentException.
Source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccess.java:1075
}
return switch (kind) {
case Boolean -> JavaConstant.forBoolean(value.readBufferByte(offset) != 0);
case Byte -> JavaConstant.forByte(value.readBufferByte(offset));
case Short -> JavaConstant.forShort(value.readBufferShort(ByteOrder.nativeOrder(), offset));
case Char -> JavaConstant.forChar((char) value.readBufferShort(ByteOrder.nativeOrder(), offset));
case Int -> JavaConstant.forInt(value.readBufferInt(ByteOrder.nativeOrder(), offset));
case Long -> JavaConstant.forLong(value.readBufferLong(ByteOrder.nativeOrder(), offset));
case Float -> JavaConstant.forFloat(value.readBufferFloat(ByteOrder.nativeOrder(), offset));
case Double -> JavaConstant.forDouble(value.readBufferDouble(ByteOrder.nativeOrder(), offset));
default -> throw new IllegalArgumentException("Unsupported kind: " + kind);
};
}
@Override
public JavaConstant createHostProxy(Object hostTarget, ResolvedJavaType guestType) {
Objects.requireNonNull(hostTarget);
if (!(Objects.requireNonNull(guestType) instanceof EspressoExternalResolvedInstanceType espressoGuestType) || !espressoGuestType.isInterface()) {
throw new IllegalArgumentException("Invalid guest type");
}
Value hostProxy = hostProxies.createHostProxy(hostTarget, espressoGuestType);
return new EspressoExternalObjectConstant(this, hostProxy);
}
@Override
public Throwable unwrapHostProxyException(JavaConstant guestWrapper) {
Objects.requireNonNull(guestWrapper);
if (!(guestWrapper instanceof EspressoExternalObjectConstant espressoWrapper)) {
return null;
}
Throwable throwable = maybeUnwrapHostException(espressoWrapper.getValue());
if (throwable == null) {
return null;
}
return throwable;
}
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Pass an interface type that the guest code uses to interact with the host object, not the host object's class
- Obtain the ResolvedJavaType from Espresso itself (e.g. vmAccess/EspressoExternalResolvedInstanceType lookup) instead of an external compiler backend
- Check guestType instanceof EspressoExternalResolvedInstanceType t && t.isInterface() before calling createHostProxy and fail with your own descriptive error
Example fix
// before
JavaConstant proxy = vmAccess.createHostProxy(hostObj, someClassType); // someClassType is a class
// after
if (!(guestType instanceof EspressoExternalResolvedInstanceType it) || !it.isInterface()) {
throw new IllegalArgumentException("guestType must be an Espresso-resolved interface: " + guestType);
}
JavaConstant proxy = vmAccess.createHostProxy(hostObj, it); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(guestType instanceof EspressoExternalResolvedInstanceType iface) || !iface.isInterface()) {
throw new IllegalArgumentException("guestType must be an Espresso-resolved interface, got: " + guestType);
} Type guard
static boolean isUsableGuestInterface(ResolvedJavaType t) {
return t instanceof EspressoExternalResolvedInstanceType e && e.isInterface();
} Try / catch
catch (IllegalArgumentException e) { /* surface which type was passed and why it is not an interface */ } Prevention
- Always resolve guest types through the same EspressoExternalVMAccess instance that builds the proxy
- Pass the interface the guest code will use, never an implementation class or array type
When it happens
Trigger: Calling vmAccess.createHostProxy(hostTarget, guestType) where guestType is a non-interface ResolvedJavaType (class, array, primitive), or a ResolvedJavaType that was not resolved through the Espresso external VM access API (e.g. obtained from a HotSpot/Economy Graal backend instead of EspressoExternalVMAccess).
Common situations: Passing a concrete guest class instead of the interface the guest code will cast the proxy to; mixing ResolvedJavaType instances from another Graal backend (graal compiler SDK types) with Espresso's external access API; passing a type resolved before the Espresso context was initialized.
Related errors
- cannot have non-public interfaces in different packages
- non-public interface is not defined by the given loader
- ${targetModule} can't access ${interfaceName}
- methods with same signature {} but incompatible return types
- methods with same signature {} but incompatible return types
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/ff24a902ff47910c.
Report an issue: GitHub.