oracle/graal · error · IllegalArgumentException

methods with same signature {} but incompatible return types

Error message

methods with same signature {} but incompatible return types: {}

What it means

The companion failure in the proxy generator's return-type coverage check: after processing all same-signature methods, if more than one return type remains 'uncovered' (none assignable from another), proxy creation aborts with the friendly signature and the list of uncovered return types. E.g. 'm()' returning both Socket and InputStream from different interfaces with neither a subtype of the other. Same rule as java.lang.reflect.Proxy.

Source

Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/EspressoForeignProxyGenerator.java:788

            }

            /*
             * If we got through the list of existing uncovered return types without an
             * assignability relationship, then add the new return type to the list of uncovered
             * ones.
             */
            if (!added) {
                uncoveredReturnTypes.add(newReturnType);
            }
        }

        /*
         * We shouldn't end up with more than one return type that is not assignable from any of the
         * others.
         */
        if (uncoveredReturnTypes.size() > 1) {
            ProxyMethod pm = methods.get(0);
            throw new IllegalArgumentException(
                            "methods with same signature " +
                                            getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +
                                            " but incompatible return types: " + uncoveredReturnTypes);
        }
    }

    /**
     * Visit a bytecode for a constant.
     *
     * @param mv The MethodVisitor
     * @param cst The constant value
     */
    private static void emitIconstInsn(MethodVisitor mv, final int cst) {
        if (cst >= -1 && cst <= 5) {
            mv.visitInsn(ICONST_0 + cst);
        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
            mv.visitIntInsn(BIPUSH, cst);
        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Proxy the conflicting interfaces separately and compose the two proxy objects behind a façade.
  2. Change one method's return type so one is assignable from the other (common supertype or interface).
  3. Rename or avoid one of the colliding methods if you own the interfaces.
  4. Inspect the uncovered list in the message to see exactly which return types conflict.

Example fix

// before
interface A { Socket connect(); }
interface B { Channel connect(); }
proxy(A.class, B.class); // throws: Socket and Channel uncovered

// after: separate proxies behind a facade
class ConnFacade { final A a; final B b; ... }
Defensive patterns

Strategy: validation

Validate before calling

// simulate Proxy's coverage rule: reduce same-signature return types to one assignable chain
List<Klass> uncovered = new ArrayList<>();
for (Klass rt : returnTypesOfSameSignature) {
    boolean covered = uncovered.removeIf(u -> u.isAssignableTo(rt));
    if (!covered && uncovered.stream().noneMatch(u -> rt.isAssignableTo(u))) uncovered.add(rt);
}
if (uncovered.size() > 1) throw new IllegalArgumentException("incompatible return types: " + uncovered);

Try / catch

try {
    generator.getProxy(context, loader, interfaces);
} catch (IllegalArgumentException e) {
    // uncoveredReturnTypes listed in message: proxy conflicting interfaces separately
}

Prevention

When it happens

Trigger: Proxying two interfaces that both declare 'X m()' and 'Y m()' where X and Y are unrelated reference types; the pairwise-assignability loop cannot reduce the uncovered set to one, so the final size>1 check throws.

Common situations: Combining generic fluent interfaces from different libraries with same-named methods; cross-version API collisions after an upgrade changed a return type; proxy composition patterns that merge unrelated SPIs.

Related errors


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