{"record":{"id":"61e1388b08fbe5ec","repo":"apache/dubbo","slug":"servicedefinitionbuilder-collection-type-0-w","errorCode":null,"errorMessage":"[ServiceDefinitionBuilder] Collection type [{0}] with unexpected amount of arguments [{1}].<Arrays.toString(actualTypeArgs)>","messagePattern":"\\[ServiceDefinitionBuilder\\] Collection type \\[(.+?)\\] with unexpected amount of arguments \\[(.+?)\\]\\.<Arrays\\.toString\\(actualTypeArgs\\)>","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java","lineNumber":52,"sourceCode":"\n    @Override\n    public boolean accept(Class<?> clazz) {\n        if (clazz == null) {\n            return false;\n        }\n        return Collection.class.isAssignableFrom(clazz);\n    }\n\n    @Override\n    public TypeDefinition build(Type type, Class<?> clazz, Map<String, TypeDefinition> typeCache) {\n        if (!(type instanceof ParameterizedType)) {\n            return new TypeDefinition(clazz.getCanonicalName());\n        }\n\n        ParameterizedType parameterizedType = (ParameterizedType) type;\n        Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();\n        if (actualTypeArgs == null || actualTypeArgs.length != 1) {\n            throw new IllegalArgumentException(MessageFormat.format(\n                    \"[ServiceDefinitionBuilder] Collection type [{0}] with unexpected amount of arguments [{1}].\"\n                            + Arrays.toString(actualTypeArgs),\n                    type,\n                    actualTypeArgs));\n        }\n\n        String colType = ClassUtils.getCanonicalNameForParameterizedType(parameterizedType);\n        TypeDefinition td = typeCache.get(colType);\n        if (td != null) {\n            return td;\n        }\n        td = new TypeDefinition(colType);\n        typeCache.put(colType, td);\n\n        Type actualType = actualTypeArgs[0];\n        TypeDefinition itemTd = null;\n        if (actualType instanceof ParameterizedType) {\n            // Nested collection or map.","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the service interface uses standard single-element collections (e.g. List<Foo>, Set<Bar>).","Avoid custom Collection subtypes with multiple type parameters for RPC method signatures.","Simplify or unwrap exotic nested generic types in the service contract."],"exampleFix":"// before\npublic interface MyService {\n    // custom multi-arg collection confuses the builder\n    MyWeirdMultiTypeContainer<String, Integer> op();\n}\n\n// after\npublic interface MyService {\n    List<String> op(); // standard single-element collection\n}","handlingStrategy":"validation","validationCode":"// Validate service method collection types have exactly one type arg\nfor (java.lang.reflect.Method m : serviceInterface.getDeclaredMethods()) {\n    checkType(m.getGenericReturnType());\n    for (Type t : m.getGenericParameterTypes()) checkType(t);\n}\n// helper\nvoid checkType(Type t) {\n    if (t instanceof ParameterizedType pt\n        && Collection.class.isAssignableFrom(\n            (Class<?>) ((ParameterizedType) t).getRawType())\n        && pt.getActualTypeArguments().length != 1) {\n        throw new IllegalArgumentException(\"Collection type must have one type arg: \" + t);\n    }\n}","typeGuard":"static boolean isWellFormedCollectionType(Type t) {\n    if (!(t instanceof ParameterizedType pt)) return true;\n    try {\n        return Collection.class.isAssignableFrom((Class<?>) pt.getRawType())\n            ? pt.getActualTypeArguments().length == 1\n            : true;\n    } catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n    // metadata build / service export\n    serviceRepository.register(serviceInterface);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Collection type\")) {\n        // simplify the offending collection generic in the service contract\n    }\n    throw e;\n}","preventionTips":["Use standard single-element collections (List<E>, Set<E>) in RPC signatures.","Avoid custom multi-type-parameter Collection subtypes in service interfaces.","Run a metadata-introspection smoke test at build time to catch exotic generics."],"tags":["metadata","reflection","generics","service-definition"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}