{"record":{"id":"63843cfeb7b7ad55","repo":"oracle/graal","slug":"for-instance-methods-the-receiver-argument-must-n-63843c","errorCode":null,"errorMessage":"For instance methods, the receiver argument must not be null","messagePattern":"For instance methods, the receiver argument must not be null","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java","lineNumber":289,"sourceCode":"        }\n        return false;\n    }\n\n    @Override\n    protected int hashCode0() {\n        return vmMethodMirror.hashCode();\n    }\n\n    /// Adapts a call to a guest Espresso method, converting between [JavaConstant] values and\n    /// the polyglot [Value]s, and back. The interop implementation in the Espresso is\n    /// `com.oracle.truffle.espresso.impl.Method.Execute#invoke`.\n    JavaConstant invoke(JavaConstant receiver, JavaConstant... arguments) {\n        if (isStatic() || isConstructor()) {\n            if (receiver != null) {\n                throw new IllegalArgumentException(\"For static methods or constructors, 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        AbstractEspressoSignature signature = getSignature();\n        int parameterCount = signature.getParameterCount(false);\n        if (parameterCount != arguments.length) {\n            throw new IllegalArgumentException(\"Expected \" + parameterCount + \" arguments, got \" + arguments.length);\n        }\n        Object[] args = new Object[arguments.length + (isConstructor() || !isStatic() ? 1 : 0)];\n        int outputArgumentOffset = 0;\n        EspressoExternalVMAccess access = getAccess();\n        if (isConstructor()) {\n            EspressoExternalResolvedInstanceType type = (EspressoExternalResolvedInstanceType) getDeclaringClass();\n            args[0] = access.unsafeAllocateInstance(type).getValue();\n            outputArgumentOffset = 1;\n        } else if (!isStatic()) {\n            if (!(receiver instanceof EspressoExternalObjectConstant objectConstant)) {\n                throw new IllegalArgumentException(\"Bad receiver: expected Object, got \" + arguments[0].getJavaKind());","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java#L271-L307","documentation":"NullPointerException thrown by EspressoExternalResolvedJavaMethod.invoke when an instance (non-static, non-constructor) method is invoked with a Java reference null receiver. The guest interop call needs an actual receiver Value to execute on, and unlike the static case there is no default; the guard fires before any marshalling. The message text is fixed ('For instance methods, the receiver argument must not be null').","triggerScenarios":"Calling invoke(...) on a virtual/interface/special method with a null receiver variable, typically because upstream code resolved a method handle but lost the receiver object, or deliberately attempted a NullPointerException-throwing call that the adapter does not emulate.","commonSituations":"Null analysis or deoptimization replay tooling that reproduces an NPE-triggering call; dataflow bugs where the receiver constant is dropped; migrating code that used reflection (which throws NPE from the guest) to the JVMCI adapter (which throws it on the host side instead).","solutions":["Null-check the receiver before invoke and surface a proper error or skip the call","If the intent is to trigger a guest NullPointerException, use the guest's interop path (Value.execute on a null receiver member) instead of this adapter","Trace where the receiver constant became null (constant folding of a null field read is a common producer)"],"exampleFix":"// before\nJavaConstant r = resolveReceiverOpt(); // may return null\nmethod.invoke(r, args);\n\n// after\nJavaConstant r = resolveReceiverOpt();\nif (r == null) {\n    throw new IllegalStateException(\"receiver constant folded to null for \" + method.getName());\n}\nmethod.invoke(r, args);","handlingStrategy":"validation","validationCode":"if (!method.isStatic() && !method.isConstructor() && receiver == null) {\n    throw new IllegalStateException(\"missing receiver for instance method \" + method.getName());\n}","typeGuard":null,"tryCatchPattern":"catch (NullPointerException e) { if (\"For instance methods, the receiver argument must not be null\".equals(e.getMessage())) { /* recover: re-resolve receiver or report */ } else throw e; }","preventionTips":["Objects.requireNonNull(receiver) at the call boundary with your own message, so failures point at your code","Track where receiver constants are produced; constant-folded null field reads are the usual source","If you need the guest NPE behavior, execute through the guest Value interop API instead"],"tags":["espresso","jvmci","method-invocation","null-receiver","npe"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}