oracle/graal · error · IllegalArgumentException

Illegal argument type: receiver of type {} could not be conv

Error message

Illegal argument type: receiver of type {} could not be converted to a {}

What it means

Thrown by HostVMAccess.invoke for instance method invocation when the receiver constant cannot be unboxed to the method's declaring class: snippetReflection.asObject(declaringClass, receiver) returned null, i.e. the receiver object is not an instance of the class that declares the method.

Source

Thrown at compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java:188

                unboxedArguments[i] = argument.asBoxedPrimitive();
            }
        }
        try {
            if (isConstructor) {
                Constructor<?> constructor = (Constructor<?>) executable;
                return snippetReflection.forObject(constructor.newInstance(unboxedArguments));
            } else {
                Method reflectionMethod = (Method) executable;
                Object unboxedReceiver;
                if (Modifier.isStatic(reflectionMethod.getModifiers())) {
                    unboxedReceiver = null;
                } else {
                    if (receiver.isNull()) {
                        unboxedReceiver = null;
                    } else {
                        unboxedReceiver = snippetReflection.asObject(reflectionMethod.getDeclaringClass(), receiver);
                        if (unboxedReceiver == null) {
                            throw new IllegalArgumentException(
                                            "Illegal argument type: receiver of type " + providers.getMetaAccess().lookupJavaType(receiver).toClassName() +
                                                            " could not be converted to a " + reflectionMethod.getDeclaringClass());
                        }
                    }
                }
                JavaKind returnKind = method.getSignature().getReturnKind();
                Object result = reflectionMethod.invoke(unboxedReceiver, unboxedArguments);
                if (returnKind == JavaKind.Void) {
                    return null;
                }
                if (returnKind.isObject()) {
                    return snippetReflection.forObject(result);
                } else {
                    return snippetReflection.forBoxed(returnKind, result);
                }
            }
        } catch (InstantiationException e) {
            throw new IllegalArgumentException(e);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Check the message: it names the receiver's actual class and the expected declaring class — resolve the method against the receiver's actual type (e.g. lookupJavaType(receiverObject).resolveMethod(...))
  2. Ensure the object you wrap is really an instance of the declaring class before forObject
  3. With duplicate class names across classloaders/modules, verify both sides use the same loaded class

Example fix

// before
ResolvedJavaMethod m = interfaceType.resolveMethod(method);      // declared on Iface
hostVM.invoke(m, snippetReflection.forObject(unrelatedObj), args); // throws

// after
ResolvedJavaMethod m = metaAccess.lookupJavaType(receiverObj.getClass()).resolveMethod(method);
hostVM.invoke(m, snippetReflection.forObject(receiverObj), args);
Defensive patterns

Strategy: type-guard

Validate before calling

Object recv = snippetReflection.asObject(reflectionMethod.getDeclaringClass(), receiver);
if (recv == null) throw new IllegalArgumentException("receiver not a " + reflectionMethod.getDeclaringClass());

Type guard

static boolean receiverMatches(ResolvedJavaMethod m, JavaConstant recv, MetaAccessProvider meta) {
    return meta.lookupJavaType(recv).isSubtypeOf(m.getDeclaringClass());
}

Try / catch

catch (IllegalArgumentException e) { re-resolve the method against the receiver's concrete type and retry once }

Prevention

When it happens

Trigger: Calling invoke on an instance method with a receiver constant whose runtime class does not extend reflectionMethod.getDeclaringClass() — e.g. resolving a method on interface/superclass A but passing a receiver of unrelated class B, or passing a receiver already wrapped for the wrong type.

Common situations: Method resolution returning a default-method or bridge on an interface while the receiver is an unrelated type; classloader/module differences producing look-alike classes with the same name; refactors where the receiver expression and the resolved method drift apart.

Related errors


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