apache/dubbo · error · IllegalArgumentException

args.length != types.length

Error message

args.length != types.length

What it means

PojoUtils.realize(Object[] objs, Class<?>[] types) is the reverse-generalization entry point: it converts generic (often Map/Primitive) representations back into typed Java objects. It enforces that the argument array and the target type array have the same length. If they differ, there is no way to align each argument to its target type, so it throws immediately.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java:113

            Short.class,
            Integer.class,
            Long.class,
            Float.class,
            Double.class,
            Boolean.class,
            Character.class);

    public static Object[] generalize(Object[] objs) {
        Object[] dests = new Object[objs.length];
        for (int i = 0; i < objs.length; i++) {
            dests[i] = generalize(objs[i]);
        }
        return dests;
    }

    public static Object[] realize(Object[] objs, Class<?>[] types) {
        if (objs.length != types.length) {
            throw new IllegalArgumentException("args.length != types.length");
        }

        Object[] dests = new Object[objs.length];
        for (int i = 0; i < objs.length; i++) {
            dests[i] = realize(objs[i], types[i]);
        }

        return dests;
    }

    public static Object[] realize(Object[] objs, Class<?>[] types, Type[] gtypes) {
        if (objs.length != types.length || objs.length != gtypes.length) {
            throw new IllegalArgumentException("args.length != types.length");
        }
        Object[] dests = new Object[objs.length];
        for (int i = 0; i < objs.length; i++) {
            dests[i] = realize(objs[i], types[i], gtypes[i]);
        }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Verify that the argument array and the parameter type array passed to realize (or to $invoke/generic invocation) have the same length.
  2. Check for consumer/provider interface version mismatch where a method signature changed (added/removed a parameter).
  3. Ensure null arguments are still represented as array elements (not omitted), since null is a valid argument but a missing slot changes the length.
  4. Log both arrays' lengths and contents before the call to pinpoint the mismatch source.

Example fix

// before
Object[] args = {"hello"};
Class<?>[] types = {String.class, Integer.class};
PojoUtils.realize(args, types); // throws: 1 != 2
// after
Object[] args = {"hello", null};
Class<?>[] types = {String.class, Integer.class};
PojoUtils.realize(args, types);
Defensive patterns

Strategy: validation

Validate before calling

// Validate array lengths match before calling realize
if (objs == null || types == null || objs.length != types.length) {
    throw new IllegalArgumentException(
        "objs.length (" + (objs == null ? "null" : objs.length)
        + ") must equal types.length (" + (types == null ? "null" : types.length) + ")");
}
PojoUtils.realize(objs, types);

Prevention

When it happens

Trigger: Calling PojoUtils.realize(objs, types) where objs.length != types.length. This typically happens inside Dubbo's generic invocation path ($invoke) where the serialized arguments and the declared parameter types from the service metadata must correspond one-to-one.

Common situations: A generic Dubbo RPC call where the number of arguments sent by the consumer does not match the number of parameter types declared in the provider interface. This can occur with version mismatches between consumer and provider interfaces, or when a generic caller builds the argument/type arrays manually and miscounts.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/7c12ad611f46006b. Report an issue: GitHub.