{"record":{"id":"11a8b604443a1144","repo":"oracle/graal","slug":"for-instance-methods-the-receiver-argument-must-n-11a8b6","errorCode":null,"errorMessage":"For instance methods, the receiver argument must not represent a null constant","messagePattern":"For instance methods, the receiver argument must not represent a null constant","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java","lineNumber":147,"sourceCode":"    public boolean owns(ResolvedJavaField value) {\n        return value.getClass().getModule() == hostImplModule;\n    }\n\n    @Override\n    public JavaConstant invoke(ResolvedJavaMethod method, JavaConstant receiver, JavaConstant... arguments) {\n        SnippetReflectionProvider snippetReflection = providers.getSnippetReflection();\n        Executable executable = snippetReflection.originalMethod(method);\n        makeAccessible(executable);\n        boolean isConstructor = executable instanceof Constructor;\n        Class<?>[] parameterTypes = executable.getParameterTypes();\n        if (Modifier.isStatic(executable.getModifiers()) || isConstructor) {\n            if (receiver != null) {\n                throw new IllegalArgumentException(\"For static methods or constructor, the receiver argument must be null\");\n            }\n        } else if (receiver == null) {\n            throw new NullPointerException(\"For instance methods, the receiver argument must not be null\");\n        } else if (receiver.isNull()) {\n            throw new IllegalArgumentException(\"For instance methods, the receiver argument must not represent a null constant\");\n        }\n        if (parameterTypes.length != arguments.length) {\n            throw new IllegalArgumentException(\"Wrong number of arguments: expected \" + parameterTypes.length + \" but got \" + arguments.length);\n        }\n        Signature signature = method.getSignature();\n        Object[] unboxedArguments = new Object[parameterTypes.length];\n        for (int i = 0; i < unboxedArguments.length; i++) {\n            JavaKind parameterKind = signature.getParameterKind(i);\n            JavaConstant argument = arguments[i];\n            if (parameterKind.isObject()) {\n                if (argument.isNull()) {\n                    unboxedArguments[i] = null;\n                } else {\n                    unboxedArguments[i] = snippetReflection.asObject(parameterTypes[i], argument);\n                    if (unboxedArguments[i] == null) {\n                        throw new IllegalArgumentException(\n                                        \"Illegal argument type: arguments[\" + i + \"] of type \" + providers.getMetaAccess().lookupJavaType(arguments[i]).toClassName() +\n                                                        \" could not be converted to a \" + parameterTypes[i]);","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java#L129-L165","documentation":"Thrown by HostVMAccess.invoke when an instance method is invoked with a JavaConstant that itself represents null (JavaConstant.isNull()). The API distinguishes 'no receiver reference' (null) from 'receiver is the null constant' — for instance calls the latter is meaningless because reflection cannot dispatch invoke on a null object.","triggerScenarios":"Calling invoke(instanceMethod, JavaConstant.NULL_POINTER, args...) or any receiver constant whose isNull() is true, for a non-static executable.","commonSituations":"Uniform code that wraps possibly-null objects with snippetReflection.forObject(x) — forObject(null) yields the null constant, which is then forwarded as receiver; unfolding a snippet where the receiver was a null-folded constant.","solutions":["Guard before invoking: if receiver != null && receiver.isNull(), either skip the call, substitute a real object, or let the caller's NPE semantics apply at the guest level","Use forObject only for non-null objects and pass null only when the method is static/constructor","If the guest program legitimately calls an instance method on null, raise/propagate the guest NullPointerException instead of invoking the host"],"exampleFix":"// before\nhostVM.invoke(instanceMethod, snippetReflection.forObject(maybeNull), args);  // null constant -> throws\n\n// after\nJavaConstant receiver = maybeNull == null ? null : snippetReflection.forObject(maybeNull);\nif (receiver != null && receiver.isNull()) {\n    throw new NullPointerException(\"receiver is null\"); // explicit guest semantics\n}\nhostVM.invoke(instanceMethod, receiver, args);","handlingStrategy":"type-guard","validationCode":"if (receiver != null && receiver.isNull()) { /* null receiver constant: do not invoke */ }","typeGuard":"static boolean isNullConstant(JavaConstant c) { return c == null || c.isNull(); }","tryCatchPattern":"catch (IllegalArgumentException e) { convert to guest NullPointerException if the guest called a method on null }","preventionTips":["forObject(null) yields the null constant — never forward its result as a receiver","Distinguish 'no receiver' (null ref) from 'null receiver' (null constant) in call sites","Fold explicit null checks before building invoke arguments"],"tags":["graalvm","hostvmaccess","reflection","null-safety"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}