quarkusio/quarkus · error · IllegalArgumentException

Converter ${converter.name()} must be parameterized with a s

Error message

Converter ${converter.name()} must be parameterized with a single type

What it means

A Converter<T> implementation must be parameterized with exactly one type argument. When the parameterized Converter interface found on the converter class has zero or more than one type argument, getConverterType throws this IllegalArgumentException.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java:1242

            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

  1. Ensure the class implements io.smallrye.config.Converter<T> with exactly one type parameter
  2. Verify the imported Converter is io.smallrye.config.Converter, not a same-named interface from another library
  3. Split any two-type converter into a single-type converter plus an adapter

Example fix

// before
public class PairConverter implements Converter<Pair, String> { ... }
// after
public class PairConverter implements Converter<Pair> { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

ParameterizedType pt = (ParameterizedType) ColorConverter.class.getGenericInterfaces()[0];
if (pt.getActualTypeArguments().length != 1) {
    throw new IllegalStateException("Converter must have exactly one type argument");
}

Type guard

static boolean hasSingleTypeArg(Class<?> c) {
    return java.util.Arrays.stream(c.getGenericInterfaces())
        .filter(t -> t instanceof ParameterizedType pt
            && pt.getRawType().equals(io.smallrye.config.Converter.class))
        .allMatch(t -> ((ParameterizedType) t).getActualTypeArguments().length == 1);
}

Prevention

When it happens

Trigger: A converter class implements a parameterized type whose raw name equals Converter but whose type-argument list size != 1, discovered while scanning interfaceTypes in config generation.

Common situations: Mistakenly implementing a multi-parameter generic interface variant or copying a generic converter signature like Converter<A, B>; accidentally matching a different Converter interface name with two parameters; IDE auto-import of the wrong Converter type.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/463a530007478635. Report an issue: GitHub.