quarkusio/quarkus · error · IllegalStateException

Unsupported parameter type used in @ClientExceptionMapper. S

Error message

Unsupported parameter type used in @ClientExceptionMapper. See the Javadoc of the annotation for the supported types. Offending instance is '${className}#${methodName}'

What it means

A @ClientExceptionMapper method may only declare parameters Quarkus knows how to provide at build time — the Response, or the invoked java.lang.reflect.Method (e.g. via RequestContext accessors). During bytecode generation, any other parameter type hits the else branch and aborts the build with this IllegalStateException.

Source

Thrown at extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/ClientExceptionMapperHandler.java:142

                    for (Type paramType : target.parameterTypes()) {
                        Expr targetMethodParamHandle;
                        DotName paramTypeName = paramType.name();
                        if (paramTypeName.equals(ResteasyReactiveDotNames.RESPONSE)) {
                            targetMethodParamHandle = response;
                        } else if (paramTypeName.equals(DotNames.METHOD)) {
                            targetMethodParamHandle = bc.invokeVirtual(GET_INVOKED_METHOD, requestContext);
                        } else if (paramTypeName.equals(DotNames.URI)) {
                            targetMethodParamHandle = bc.invokeVirtual(GET_URI, requestContext);
                        } else if (isMapStringToObject(paramType)) {
                            targetMethodParamHandle = bc.invokeVirtual(GET_PROPERTIES, requestContext);
                        } else if (isMultivaluedMapStringToString(paramType)) {
                            targetMethodParamHandle = bc.invokeVirtual(GET_REQUEST_HEADERS_AS_MAP, requestContext);
                        } else {
                            String message = "Unsupported parameter type used in " + DotNames.CLIENT_EXCEPTION_MAPPER
                                    + ". See the Javadoc of the annotation for the supported types."
                                    + " Offending instance is '" + target.declaringClass().name().toString() + "#"
                                    + target.name() + "'";
                            throw new IllegalStateException(message);
                        }
                        targetMethodParams.put(paramTypeName.toString(), targetMethodParamHandle);
                    }

                    Expr resultHandle = bc.invokeStatic(methodDescOf(target),
                            targetMethodParams.values().toArray(new Expr[0]));
                    bc.return_(resultHandle);
                });
            });

            if (finalPriority != Priorities.USER) {
                cc.method("getPriority", mc -> {
                    mc.returning(int.class);
                    mc.body(bc -> {
                        bc.return_(Const.of(finalPriority));
                    });
                });
            }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Reduce the method signature to only supported parameters: jakarta.ws.rs.core.Response and/or java.lang.reflect.Method
  2. If you need headers/status, extract them inside the method body from the Response parameter instead of receiving them as parameters
  3. Consult the @ClientExceptionMapper Javadoc for the exhaustive list of supported parameter types

Example fix

// before
@ClientExceptionMapper
static RuntimeException map(Response r, String endpoint) { ... } // 'endpoint' unsupported
// after
@ClientExceptionMapper
static RuntimeException map(Response r) {
    String endpoint = r.getLocation() != null ? r.getLocation().toString() : null;
    return new RuntimeException("failed: " + endpoint);
}
Defensive patterns

Strategy: validation

Validate before calling

static boolean supportedParams(Method m) {
    for (Class<?> p : m.getParameterTypes()) {
        if (p != jakarta.ws.rs.core.Response.class && p != java.lang.reflect.Method.class) return false;
    }
    return true;
}

Try / catch

try {
    handler.generateResponseExceptionMapper(classResult, instance);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Unsupported parameter type")) { /* reduce params */ }
    throw e;
}

Prevention

When it happens

Trigger: Declaring a @ClientExceptionMapper static method with a parameter of an unsupported type (e.g. String, URI, custom context objects, or a Map obtained through an unsupported accessor).

Common situations: Copy-pasting server-side @ServerExceptionMapper signatures (which accept more types); adding extra 'helpful' parameters; upgrading Quarkus where previously-lenient parameter handling was tightened.

Related errors


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