quarkusio/quarkus · error · IllegalArgumentException
Can not add converter ${converter.name()} that is not parame
Error message
Can not add converter ${converter.name()} that is not parameterized with a type What it means
A SmallRye Config converter must implement Converter<T> parameterized with a concrete type so the framework knows which config value type it converts. If the converter class has no parameterized interface type (or is Object), getConverterType throws this IllegalArgumentException because the target type cannot be derived.
Source
Thrown at core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java:1232
for (String prefix : entry.getValue()) {
configClasses.add(ConfigClass.configClass(loadClass(entry.getKey()), prefix));
}
}
return configClasses;
}
private static Class<?> loadClass(final String name) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
return classLoader.loadClass(name);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("The class (" + name + ") cannot be created during deployment.", e);
}
}
private static Type getConverterType(final ClassInfo converter, final CombinedIndexBuildItem combinedIndex) {
if (converter.name().toString().equals(Object.class.getName())) {
throw new IllegalArgumentException(
"Can not add converter " + converter.name() + " that is not parameterized with a type");
}
for (Type type : converter.interfaceTypes()) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = type.asParameterizedType();
if (parameterizedType.name().equals(CONVERTER_NAME)) {
List<Type> arguments = parameterizedType.arguments();
if (arguments.size() != 1) {
throw new IllegalArgumentException(
"Converter " + converter.name() + " must be parameterized with a single type");
}
return arguments.get(0);
}
}
}
return getConverterType(combinedIndex.getComputingIndex().getClassByName(converter.superName()), combinedIndex);View on GitHub (pinned to e1c734241f)
Solutions
- Parameterize the Converter interface with the concrete converted type, e.g. class ColorConverter implements Converter<Color>
- If a converter is intentionally generic, register it explicitly via @Priority/@RegisterConverter mechanisms that accept an explicit type rather than relying on inference
- Check that the class implements io.smallrye.config.Converter directly (via interfaceTypes) and not just an unrelated interface
Example fix
// before
public class ColorConverter implements Converter { ... }
// after
public class ColorConverter implements Converter<Color> { ... } Defensive patterns
Strategy: type-guard
Validate before calling
for (java.lang.reflect.Type iface : ColorConverter.class.getGenericInterfaces()) {
if (iface instanceof ParameterizedType pt
&& pt.getRawType() == io.smallrye.config.Converter.class
&& pt.getActualTypeArguments().length == 1) {
return; // OK
}
}
throw new IllegalStateException("Converter must implement Converter<T> with one type argument"); Type guard
static boolean isValidConverter(Class<?> c) {
return java.util.Arrays.stream(c.getGenericInterfaces())
.anyMatch(t -> t instanceof ParameterizedType pt
&& pt.getRawType().equals(io.smallrye.config.Converter.class)
&& pt.getActualTypeArguments().length == 1
&& !(pt.getActualTypeArguments()[0] instanceof Object));
} Prevention
- Always parameterize Converter with a concrete type
- Enable IDE raw-types/unchecked warnings and fix them
- Don't cast converters to raw Converter in shared code
- Test converter registration in a unit test before building
When it happens
Trigger: A registered converter class implements raw Converter or Converter<Object> (i.e. no parameterized Converter interface with a real type argument) and is discovered during config generation.
Common situations: Writing a converter without generics (implements Converter instead of Converter<MyType>); after type-erasure refactors a raw type was introduced; anonymous/inner converter classes whose generic info was dropped.
Related errors
- Converter ${converter.name()} must be parameterized with a s
- A generic type is not allowed here; try creating a subclass
- Unsupported wildcard type: ${wildcard}
- The class (${name}) cannot be created during deployment.
- The supplied 'main-class' value of '${mainClassName}' does n
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/272ec14500eaf7eb.
Report an issue: GitHub.