{"record":{"id":"1d4486c75350a6eb","repo":"oracle/graal","slug":"for-static-methods-or-constructor-the-receiver-ar","errorCode":null,"errorMessage":"For static methods or constructor, the receiver argument must be null","messagePattern":"For static methods or constructor, the receiver argument must be null","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java","lineNumber":142,"sourceCode":"    public boolean owns(ResolvedJavaMethod value) {\n        return value.getClass().getModule() == hostImplModule;\n    }\n\n    @Override\n    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 {","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccess.java#L124-L160","documentation":"Thrown by HostVMAccess.invoke when invoking a static method or a constructor with a non-null receiver JavaConstant. Reflection semantics require no receiver for static/constructor execution, so this is an API-contract violation by the caller, not a runtime failure of the target code.","triggerScenarios":"Calling invoke(method, receiver, args...) where method maps to a static Executable or a Constructor and receiver is any non-null JavaConstant (even JavaConstant.NULL_POINTER counts as non-null here).","commonSituations":"Generic invocation code that always forwards a receiver constant (e.g. a snippet host or a test harness that reuses one call path for instance and static methods), or misclassifying a method as instance because Modifier.isStatic was checked on the wrong mirror after snippet substitution.","solutions":["Pass null as receiver when the executable is static or a constructor","Branch on Modifier.isStatic(executable.getModifiers()) / instanceof Constructor before building the call, mirroring the guard in HostVMAccess","If you expected an instance method, verify the ResolvedJavaMethod really resolves to a non-static original via SnippetReflectionProvider.originalMethod"],"exampleFix":"// before\nhostVM.invoke(staticMethod, snippetReflection.forObject(obj), args);  // throws\n\n// after\nObject receiverConst = Modifier.isStatic(executable.getModifiers()) || executable instanceof Constructor\n        ? null\n        : snippetReflection.forObject(obj);\nhostVM.invoke(staticMethod, receiverConst, args);","handlingStrategy":"validation","validationCode":"Executable ex = snippetReflection.originalMethod(method);\nboolean noReceiver = Modifier.isStatic(ex.getModifiers()) || ex instanceof Constructor;\nif (noReceiver && receiver != null) throw new IllegalArgumentException(\"receiver must be null\");","typeGuard":"static boolean takesReceiver(Executable ex) { return !Modifier.isStatic(ex.getModifiers()) && !(ex instanceof Constructor); }","tryCatchPattern":"catch (IllegalArgumentException e) { fail fast with the executable identity in the message }","preventionTips":["Always branch on staticness/constructor before constructing the receiver","Centralize invoke calls in one helper that owns the receiver rule","Never forward a 'default' receiver constant blindly"],"tags":["graalvm","hostvmaccess","reflection","api-contract"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}