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

  1. Pass an interface type that the guest code uses to interact with the host object, not the host object's class
  2. Obtain the ResolvedJavaType from Espresso itself (e.g. vmAccess/EspressoExternalResolvedInstanceType lookup) instead of an external compiler backend
  3. 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

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


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