{"record":{"id":"a6030d892b876a4d","repo":"gradle/gradle","slug":"cannot-convert-object-of-s-to-s","errorCode":null,"errorMessage":"Cannot convert object of %s to %s.","messagePattern":"Cannot convert object of (.+?) to (.+?)\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"platforms/ide/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/ProtocolToModelAdapter.java","lineNumber":369,"sourceCode":"                if (Iterable.class.isAssignableFrom(rawClass)) {\n                    Type targetElementType = getElementType(parameterizedTargetType, 0);\n                    return convertCollectionInternal(rawClass, targetElementType, (Iterable<?>) sourceObject, decoration, graphDetails);\n                }\n                if (Map.class.isAssignableFrom(rawClass)) {\n                    Type targetKeyType = getElementType(parameterizedTargetType, 0);\n                    Type targetValueType = getElementType(parameterizedTargetType, 1);\n                    return convertMap(rawClass, targetKeyType, targetValueType, (Map<?, ?>) sourceObject, decoration, graphDetails);\n                }\n            }\n        }\n        if (targetType instanceof Class) {\n            Class<Object> targetClassType = Cast.uncheckedNonnullCast(targetType);\n            if (targetClassType.isPrimitive()) {\n                return sourceObject;\n            }\n            return createView(targetClassType, sourceObject, decoration, graphDetails);\n        }\n        throw new UnsupportedOperationException(String.format(\"Cannot convert object of %s to %s.\", sourceObject.getClass(), targetType));\n    }\n\n    private static Map<Object, Object> convertMap(Class<?> mapClass, Type targetKeyType, Type targetValueType, Map<?, ?> sourceObject, ViewDecoration decoration, ViewGraphDetails graphDetails) {\n        Map<Object, Object> convertedElements = COLLECTION_MAPPER.createEmptyMap(mapClass);\n        for (Map.Entry<?, ?> entry : sourceObject.entrySet()) {\n            convertedElements.put(convert(targetKeyType, entry.getKey(), decoration, graphDetails), convert(targetValueType, entry.getValue(), decoration, graphDetails));\n        }\n        return convertedElements;\n    }\n\n    private static Object convertCollectionInternal(Class<?> collectionClass, Type targetElementType, Iterable<?> sourceObject, ViewDecoration decoration, ViewGraphDetails graphDetails) {\n        Collection<Object> convertedElements = COLLECTION_MAPPER.createEmptyCollection(collectionClass);\n        convertCollectionInternal(convertedElements, targetElementType, sourceObject, decoration, graphDetails);\n        if (collectionClass.equals(DomainObjectSet.class)) {\n            return new ImmutableDomainObjectSet<Object>(convertedElements);\n        } else {\n            return convertedElements;\n        }","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/ide/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/ProtocolToModelAdapter.java#L351-L387","documentation":"The Tooling API's ProtocolToModelAdapter adapts provider-side protocol objects into the consumer's model interfaces. Its convert() dispatch knows how to build maps, collections, primitives and interface-backed proxy views; when the requested target java.lang.reflect.Type matches none of those strategies, it throws this UnsupportedOperationException, naming both the concrete source class and the unsupported target type.","triggerScenarios":"Fetching a tooling model (ProjectConnection.model(...) or a BuildAction result) whose interface declares a method whose return or element type the adapter cannot map: an unresolved type variable, a wildcard or generic-array type, or another exotic Type that is neither a plain Class nor a handled parameterized type. Also reachable when code reuses ProtocolToModelAdapter.convert/unpack directly with a raw Type.","commonSituations":"Custom tooling-model plugins exposing generic-heavy or unusual types; version skew where a newer Tooling API consumer talks to an older Gradle provider (or vice versa) so the conversion tables disagree; model interfaces that evolved between Gradle versions.","solutions":["Simplify the tooling model interface to types the adapter supports: primitives, String, File, enums, List/Set/Map of supported types, and nested model interfaces.","Align the consumer's Tooling API artifact version with the target Gradle version so both sides agree on the model shapes.","If you drive ProtocolToModelAdapter yourself, pass a concrete Class or a supported parameterized type (List<T>, Map<K,V>) instead of an unresolved generic Type."],"exampleFix":"// before\npublic interface CustomModel {\n    <T> Type metadata(); // adapter cannot convert to an unresolved generic Type\n}\n\n// after\npublic interface CustomModel {\n    CustomMetadata metadata(); // a nested model interface the adapter can proxy\n}","handlingStrategy":"try-catch","validationCode":"static boolean usesSupportedModelTypes(Class<?> model) {\n    for (Method m : model.getMethods()) {\n        Type t = m.getGenericReturnType();\n        if (t instanceof TypeVariable || t instanceof WildcardType || t instanceof GenericArrayType) return false;\n        if (t instanceof ParameterizedType) {\n            for (Type arg : ((ParameterizedType) t).getActualTypeArguments()) {\n                if (!(arg instanceof Class)) return false;\n            }\n        }\n    }\n    return true;\n}\n// before connecting: if (!usesSupportedModelTypes(MyModel.class)) fail with your own message","typeGuard":null,"tryCatchPattern":"try {\n    MyModel model = connection.model(MyModel.class).get();\n} catch (UnsupportedOperationException e) {\n    // message names source class and unsupported target type; log both, then\n    // fix the model interface or align consumer/provider versions\n}","preventionTips":["Keep tooling model interfaces to primitives, String, File, enums, collections/maps, and nested model interfaces.","Pin the tooling-api artifact version to match the newest target Gradle you support.","Add a unit test that reflects over your model interfaces and fails on generic or exotic types."],"tags":["gradle","tooling-api","type-conversion","model","adapter"],"backgroundTag":"unsupported-type-conversion","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}