apache/dubbo · error · IllegalArgumentException

[ServiceDefinitionBuilder] Collection type [{0}] with unexpe

Error message

[ServiceDefinitionBuilder] Collection type [{0}] with unexpected amount of arguments [{1}].<Arrays.toString(actualTypeArgs)>

What it means

Thrown by CollectionTypeBuilder.build when a parameterized Collection type does not have exactly one type argument. Dubbo's metadata definition expects collections (List, Set, etc.) to carry a single element type; zero or multiple arguments indicate a malformed or unsupported type and are rejected during service-metadata building.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java:52

    @Override
    public boolean accept(Class<?> clazz) {
        if (clazz == null) {
            return false;
        }
        return Collection.class.isAssignableFrom(clazz);
    }

    @Override
    public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {
        if (!(type instanceof ParameterizedType)) {
            return new TypeDefinition(clazz.getCanonicalName());
        }

        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
        if (actualTypeArgs == null || actualTypeArgs.length != 1) {
            throw new IllegalArgumentException(MessageFormat.format(
                    "[ServiceDefinitionBuilder] Collection type [{0}] with unexpected amount of arguments [{1}]."
                            + Arrays.toString(actualTypeArgs),
                    type,
                    actualTypeArgs));
        }

        String colType = ClassUtils.getCanonicalNameForParameterizedType(parameterizedType);
        TypeDefinition td = typeCache.get(colType);
        if (td != null) {
            return td;
        }
        td = new TypeDefinition(colType);
        typeCache.put(colType, td);

        Type actualType = actualTypeArgs[0];
        TypeDefinition itemTd = null;
        if (actualType instanceof ParameterizedType) {
            // Nested collection or map.

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Ensure the service interface uses standard single-element collections (e.g. List<Foo>, Set<Bar>).
  2. Avoid custom Collection subtypes with multiple type parameters for RPC method signatures.
  3. Simplify or unwrap exotic nested generic types in the service contract.

Example fix

// before
public interface MyService {
    // custom multi-arg collection confuses the builder
    MyWeirdMultiTypeContainer<String, Integer> op();
}

// after
public interface MyService {
    List<String> op(); // standard single-element collection
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate service method collection types have exactly one type arg
for (java.lang.reflect.Method m : serviceInterface.getDeclaredMethods()) {
    checkType(m.getGenericReturnType());
    for (Type t : m.getGenericParameterTypes()) checkType(t);
}
// helper
void checkType(Type t) {
    if (t instanceof ParameterizedType pt
        && Collection.class.isAssignableFrom(
            (Class<?>) ((ParameterizedType) t).getRawType())
        && pt.getActualTypeArguments().length != 1) {
        throw new IllegalArgumentException("Collection type must have one type arg: " + t);
    }
}

Type guard

static boolean isWellFormedCollectionType(Type t) {
    if (!(t instanceof ParameterizedType pt)) return true;
    try {
        return Collection.class.isAssignableFrom((Class<?>) pt.getRawType())
            ? pt.getActualTypeArguments().length == 1
            : true;
    } catch (Exception e) { return false; }
}

Try / catch

try {
    // metadata build / service export
    serviceRepository.register(serviceInterface);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Collection type")) {
        // simplify the offending collection generic in the service contract
    }
    throw e;
}

Prevention

When it happens

Trigger: Building service metadata (TypeDefinition) for a service method whose parameter/return type is a parameterized Collection with actualTypeArguments.length != 1. This runs during metadata introspection, e.g. when registering/exposing a service or generating repository metadata.

Common situations: A raw collection type that somehow reports zero type args in a non-standard JVM/library. A custom Collection subtype with unusual generic arity. Bizarre nested generics that defeat the builder's single-arg assumption. JVM/library reflection quirks on synthetic types.

Related errors


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