quarkusio/quarkus · error · IllegalArgumentException

Unsupported param type: " + paramType

Error message

Unsupported param type: " + paramType

What it means

During build-time bytecode generation, the Quarkus reactive-routes extension generates route handler code that converts String request parameters into the method's declared parameter types (Integer, Long, Float, Double, Character, etc.). If a route method declares a parameter whose type has no conversion recipe, the generated bytecode factory throws IllegalArgumentException at build time.

Source

Thrown at extensions/reactive-routes/deployment/src/main/java/io/quarkus/vertx/web/deployment/ReactiveRoutesProcessor.java:1736

                tc.body(b2 -> {
                    if (paramType.name().equals(DotName.BOOLEAN_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.BOOLEAN_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.BYTE_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.BYTE_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.SHORT_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.SHORT_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.INTEGER_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.INTEGER_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.LONG_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.LONG_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.FLOAT_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.FLOAT_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.DOUBLE_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.DOUBLE_VALUE_OF, param));
                    } else if (paramType.name().equals(DotName.CHARACTER_CLASS_NAME)) {
                        b2.set(param, b2.invokeStatic(Methods.CHARACTER_VALUE_OF, b2.withString(param).charAt(0)));
                    } else {
                        throw new IllegalArgumentException("Unsupported param type: " + paramType);
                    }
                });
                tc.catch_(Throwable.class, "e", (b2, e) -> {
                    b2.throw_(b2.new_(ConstructorDesc.of(IllegalArgumentException.class, String.class, Throwable.class),
                            Const.of("Error converting parameter #" + methodParam.position() + " of method "
                                    + methodParam.method().declaringClass() + "." + methodParam.method().name() + "()"),
                            e));
                });
            });
        });

    }

    @FunctionalInterface
    interface ValueProvider {
        Expr get(MethodParameterInfo methodParam, Set<AnnotationInstance> annotations, Var routingContext,
                BlockCreator bc, BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the route method parameter to a supported type (String, Integer, Long, Float, Double, Character, boolean/Boolean primitives) and convert manually inside the method.
  2. Accept the parameter as String and parse it in the method body (e.g. LocalDate.parse(param)).
  3. Register a custom converter or wrap the value in a class the extension supports; check the reactive-routes documentation for the current list of supported param types.

Example fix

// before
@Route(path = "/by-date", methods = HttpMethod.GET)
public Uni<String> byDate(@Param("d") LocalDate d) { ... }
// after
@Route(path = "/by-date", methods = HttpMethod.GET)
public Uni<String> byDate(@Param("d") String d) {
    LocalDate date = LocalDate.parse(d);
    ...
}
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> SUPPORTED = Set.of("java.lang.String","java.lang.Integer","java.lang.Long","java.lang.Float","java.lang.Double","java.lang.Character","java.lang.Boolean");
void checkParamTypes(Class<?>[] types) {
    for (Class<?> t : types)
        if (!SUPPORTED.contains(t.getName()))
            throw new IllegalArgumentException("Unsupported route param type: " + t);
}

Prevention

When it happens

Trigger: Declaring a @Route-annotated method with a @Param (query/path parameter) whose type is not one of the supported boxed primitives (e.g. a LocalDate, UUID, BigDecimal, or custom POJO parameter).

Common situations: Migrating an app to reactive routes and reusing DTO types for parameters; assuming automatic conversion for date/time or numeric wrapper types like BigInteger; copying a controller from Spring where richer parameter binding exists.

Related errors


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