oracle/graal · error · IllegalArgumentException

For instance methods, the receiver argument must not represe

Error message

For instance methods, the receiver argument must not represent a null constant

What it means

Thrown by EspressoExternalResolvedJavaMethod.invoke when an instance method is invoked with a JavaConstant that represents null (isNull() == true) rather than a Java null reference. The adapter distinguishes a missing receiver (NPE, previous guard) from a present-but-null constant: even if you wrap null in a constant object, interop execution on a null guest Value is impossible, so it rejects with IllegalArgumentException. This catches constants produced by JavaConstant.NULL_POINTER or equivalent null-representing constants from another backend.

Source

Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalResolvedJavaMethod.java:291

    }

    @Override
    protected int hashCode0() {
        return vmMethodMirror.hashCode();
    }

    /// Adapts a call to a guest Espresso method, converting between [JavaConstant] values and
    /// the polyglot [Value]s, and back. The interop implementation in the Espresso is
    /// `com.oracle.truffle.espresso.impl.Method.Execute#invoke`.
    JavaConstant invoke(JavaConstant receiver, JavaConstant... arguments) {
        if (isStatic() || isConstructor()) {
            if (receiver != null) {
                throw new IllegalArgumentException("For static methods or constructors, the receiver argument must be null");
            }
        } else if (receiver == null) {
            throw new NullPointerException("For instance methods, the receiver argument must not be null");
        } else if (receiver.isNull()) {
            throw new IllegalArgumentException("For instance methods, the receiver argument must not represent a null constant");
        }
        AbstractEspressoSignature signature = getSignature();
        int parameterCount = signature.getParameterCount(false);
        if (parameterCount != arguments.length) {
            throw new IllegalArgumentException("Expected " + parameterCount + " arguments, got " + arguments.length);
        }
        Object[] args = new Object[arguments.length + (isConstructor() || !isStatic() ? 1 : 0)];
        int outputArgumentOffset = 0;
        EspressoExternalVMAccess access = getAccess();
        if (isConstructor()) {
            EspressoExternalResolvedInstanceType type = (EspressoExternalResolvedInstanceType) getDeclaringClass();
            args[0] = access.unsafeAllocateInstance(type).getValue();
            outputArgumentOffset = 1;
        } else if (!isStatic()) {
            if (!(receiver instanceof EspressoExternalObjectConstant objectConstant)) {
                throw new IllegalArgumentException("Bad receiver: expected Object, got " + arguments[0].getJavaKind());
            }
            args[0] = objectConstant.getValue();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Convert null-representing constants to a Java null reference before calling invoke (receiver.isNull() ? null : receiver)
  2. If the goal is a guest NPE, execute through the guest polyglot Value API rather than the JVMCI adapter
  3. Audit producers that return JavaConstant.NULL_POINTER where callers expect nullable Java references

Example fix

// before
JavaConstant receiver = provider.forObject(null); // NULL_POINTER constant
method.invoke(receiver, args);

// after
JavaConstant receiver = provider.forObject(null);
method.invoke(receiver.isNull() ? null : receiver, args); // adapter NPE path is explicit
Defensive patterns

Strategy: validation

Validate before calling

if (receiver != null && receiver.isNull()) {
    throw new IllegalStateException("null constant receiver for " + method.getName() + " — pass Java null or fix upstream");
}

Prevention

When it happens

Trigger: Passing JavaConstant.NULL_POINTER (or a foreign backend's null constant) as the receiver to an instance method invoke; constants obtained from ConstantReflectionProvider forObject(null)-style APIs; defaulted constants (isDefaultForKind) reused as receivers.

Common situations: Uniform constant pipelines that represent 'absent object' as a null constant instead of a Java null; replayer/snapshot tools that serialize receivers and deserialize null as a constant; guest code that legitimately calls a method on null and the harness forwards the null constant verbatim.

Related errors


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