{"record":{"id":"57de66204eda8556","repo":"gradle/gradle","slug":"cannot-convert-a-collection-to-type-s","errorCode":null,"errorMessage":"Cannot convert a Collection to type %s.","messagePattern":"Cannot convert a Collection to type (.+?)\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"platforms/ide/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CollectionMapper.java","lineNumber":43,"sourceCode":"import java.util.Map;\nimport java.util.TreeMap;\nimport java.util.TreeSet;\n\nclass CollectionMapper {\n    Collection<Object> createEmptyCollection(Class<?> collectionType) {\n        if (collectionType.equals(DomainObjectSet.class)) {\n            return new ArrayList<Object>();\n        }\n        if (collectionType.isAssignableFrom(ArrayList.class)) {\n            return new ArrayList<Object>();\n        }\n        if (collectionType.isAssignableFrom(LinkedHashSet.class)) {\n            return new LinkedHashSet<Object>();\n        }\n        if (collectionType.isAssignableFrom(TreeSet.class)) {\n            return new TreeSet<Object>();\n        }\n        throw new UnsupportedOperationException(String.format(\"Cannot convert a Collection to type %s.\", collectionType.getName()));\n    }\n\n    Map<Object, Object> createEmptyMap(Class<?> mapType) {\n        if (mapType.isAssignableFrom(LinkedHashMap.class)) {\n            return new LinkedHashMap<Object, Object>();\n        }\n        if (mapType.isAssignableFrom(TreeMap.class)) {\n            return new TreeMap<Object, Object>();\n        }\n        throw new UnsupportedOperationException(String.format(\"Cannot convert a Map to type %s.\", mapType.getName()));\n    }\n}\n","sourceCodeStart":25,"sourceCodeEnd":56,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/ide/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/CollectionMapper.java#L25-L56","documentation":"ProtocolToModelAdapter copies provider-side tooling model data into the client's view interfaces. CollectionMapper.createEmptyCollection can only instantiate ArrayList, LinkedHashSet, or TreeSet (plus DomainObjectSet); when the view interface's collection return type accepts none of those (Queue, Deque, Stack, a custom collection class), it throws UnsupportedOperationException naming the unsupported type.","triggerScenarios":"Declaring a custom tooling model interface with a getter returning an unsupported collection type, e.g. Queue<String> getHistory() or MyCustomList getItems(), then fetching that model from a ProjectConnection.","commonSituations":"Custom tooling models in plugins consumed by IDEs or CI where the author used an exotic collection type; refactor from List to a domain-specific collection class; model interfaces generated with strict types.","solutions":["Change the model getter to List, Set, or SortedSet (the adapter maps these to ArrayList/LinkedHashSet/TreeSet)","Fetch the standard type and convert client-side: new ArrayDeque<>(model.getHistory())","Keep tooling model interfaces limited to JDK-standard collection abstractions"],"exampleFix":"// before\npublic interface MyToolingModel {\n    Queue<String> getPendingOperations(); // adapter cannot build a Queue -> throws\n}\n\n// after\npublic interface MyToolingModel {\n    List<String> getPendingOperations();\n}\n// client converts if needed: new ArrayDeque<>(model.getPendingOperations())","handlingStrategy":"validation","validationCode":"// reject unsupported collection types before publishing a model interface\nprivate static final Set<Class<?>> SUPPORTED = Set.of(\n    Collection.class, List.class, Set.class, SortedSet.class, DomainObjectSet.class);\n\nstatic void checkCollectionType(Class<?> type) {\n    if (!SUPPORTED.contains(type)) {\n        throw new IllegalArgumentException(\"Unsupported tooling-model collection type: \" + type.getName());\n    }\n}","typeGuard":"static boolean isSupportedCollectionType(Class<?> type) {\n    return Collection.class.equals(type) || List.class.equals(type) || Set.class.equals(type)\n        || SortedSet.class.equals(type) || DomainObjectSet.class.equals(type);\n}","tryCatchPattern":null,"preventionTips":["Declare tooling model getters as List/Set/SortedSet only; never Queue, Deque, or custom collection classes","Convert to exotic collection types client-side after fetching the model","Add a build-time check or review rule for model interface return types"],"tags":["tooling-api","model-adapter","collections","unsupported-type","gradle"],"backgroundTag":"unsupported-type-conversion","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}