gradle/gradle · error · UnsupportedOperationException
Cannot convert object of %s to %s.
Error message
Cannot convert object of %s to %s.
What it means
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.
Source
Thrown at platforms/ide/tooling-api/src/main/java/org/gradle/tooling/internal/adapter/ProtocolToModelAdapter.java:369
if (Iterable.class.isAssignableFrom(rawClass)) {
Type targetElementType = getElementType(parameterizedTargetType, 0);
return convertCollectionInternal(rawClass, targetElementType, (Iterable<?>) sourceObject, decoration, graphDetails);
}
if (Map.class.isAssignableFrom(rawClass)) {
Type targetKeyType = getElementType(parameterizedTargetType, 0);
Type targetValueType = getElementType(parameterizedTargetType, 1);
return convertMap(rawClass, targetKeyType, targetValueType, (Map<?, ?>) sourceObject, decoration, graphDetails);
}
}
}
if (targetType instanceof Class) {
Class<Object> targetClassType = Cast.uncheckedNonnullCast(targetType);
if (targetClassType.isPrimitive()) {
return sourceObject;
}
return createView(targetClassType, sourceObject, decoration, graphDetails);
}
throw new UnsupportedOperationException(String.format("Cannot convert object of %s to %s.", sourceObject.getClass(), targetType));
}
private static Map<Object, Object> convertMap(Class<?> mapClass, Type targetKeyType, Type targetValueType, Map<?, ?> sourceObject, ViewDecoration decoration, ViewGraphDetails graphDetails) {
Map<Object, Object> convertedElements = COLLECTION_MAPPER.createEmptyMap(mapClass);
for (Map.Entry<?, ?> entry : sourceObject.entrySet()) {
convertedElements.put(convert(targetKeyType, entry.getKey(), decoration, graphDetails), convert(targetValueType, entry.getValue(), decoration, graphDetails));
}
return convertedElements;
}
private static Object convertCollectionInternal(Class<?> collectionClass, Type targetElementType, Iterable<?> sourceObject, ViewDecoration decoration, ViewGraphDetails graphDetails) {
Collection<Object> convertedElements = COLLECTION_MAPPER.createEmptyCollection(collectionClass);
convertCollectionInternal(convertedElements, targetElementType, sourceObject, decoration, graphDetails);
if (collectionClass.equals(DomainObjectSet.class)) {
return new ImmutableDomainObjectSet<Object>(convertedElements);
} else {
return convertedElements;
}View on GitHub (pinned to 534f27719b)
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.
Example fix
// before
public interface CustomModel {
<T> Type metadata(); // adapter cannot convert to an unresolved generic Type
}
// after
public interface CustomModel {
CustomMetadata metadata(); // a nested model interface the adapter can proxy
} Defensive patterns
Strategy: try-catch
Validate before calling
static boolean usesSupportedModelTypes(Class<?> model) {
for (Method m : model.getMethods()) {
Type t = m.getGenericReturnType();
if (t instanceof TypeVariable || t instanceof WildcardType || t instanceof GenericArrayType) return false;
if (t instanceof ParameterizedType) {
for (Type arg : ((ParameterizedType) t).getActualTypeArguments()) {
if (!(arg instanceof Class)) return false;
}
}
}
return true;
}
// before connecting: if (!usesSupportedModelTypes(MyModel.class)) fail with your own message Try / catch
try {
MyModel model = connection.model(MyModel.class).get();
} catch (UnsupportedOperationException e) {
// message names source class and unsupported target type; log both, then
// fix the model interface or align consumer/provider versions
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- The given object is not a view object
- Cannot fetch a model of type '%s' as this type is not an int
- The '%s' cannot be used with FactoryNamedDomainObjectContain
- Cannot convert string value '%s' to an enum value of type '%
- Cannot convert value '%s' of type '%s' to enum type '%s'
AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22).
Data as JSON: /api/errors/a6030d892b876a4d.
Report an issue: GitHub.