quarkusio/quarkus · error · WebSocketException

Global error handlers may not accept @PathParam parameters:

Error message

Global error handlers may not accept @PathParam parameters: %s

What it means

Global error handlers (declared with WebSocketGlobalErrorHandling / global @OnError) are not bound to an endpoint path, so @PathParam parameters cannot be resolved there. If a global error handler declares a @PathParam parameter, the build fails with WebSocketException. Path parameters are only meaningful for callbacks attached to an endpoint with a path template.

Source

Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/PathParamCallbackArgument.java:28

import io.quarkus.arc.processor.Annotations;
import io.quarkus.gizmo2.Const;
import io.quarkus.gizmo2.Expr;
import io.quarkus.gizmo2.desc.MethodDesc;
import io.quarkus.websockets.next.WebSocketException;
import io.quarkus.websockets.next.runtime.WebSocketConnectionBase;

class PathParamCallbackArgument implements CallbackArgument {

    @Override
    public boolean matches(ParameterContext context) {
        String name = getParamName(context);
        if (name != null) {
            if (!context.parameter().type().name().equals(WebSocketDotNames.STRING)) {
                throw new WebSocketException("Method parameter annotated with @PathParam must be java.lang.String: "
                        + WebSocketProcessor.methodToString(context.parameter().method()));
            }
            if (context.endpointPath() == null) {
                throw new WebSocketException("Global error handlers may not accept @PathParam parameters: "
                        + WebSocketProcessor.methodToString(context.parameter().method()));
            }
            List<String> pathParams = getPathParamNames(context.endpointPath());
            if (!pathParams.contains(name)) {
                throw new WebSocketException(
                        String.format(
                                "@PathParam name [%s] must be used in the endpoint path [%s]: %s", name,
                                context.endpointPath(),
                                WebSocketProcessor.methodToString(context.parameter().method())));
            }
            return true;
        }
        return false;
    }

    @Override
    public Expr get(InvocationBytecodeContext context) {
        String paramName = getParamName(context);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the @PathParam parameter from the global error handler
  2. Move the error-handling method into the specific @WebSocket endpoint where the path param exists
  3. Access connection-level information via WebSocketConnection parameters instead of path params

Example fix

// before (global handler)
@OnError
void onError(WebSocketConnection conn, @PathParam("id") String id, Throwable t) { }
// after
@OnError
void onError(WebSocketConnection conn, Throwable t) { }
Defensive patterns

Strategy: validation

Validate before calling

// Global error handlers: assert no @PathParam parameters exist
boolean hasPathParam = Arrays.stream(handler.getParameters())
    .anyMatch(p -> p.isAnnotationPresent(PathParam.class));

Prevention

When it happens

Trigger: Declaring @PathParam on a parameter of a global @OnError handler method (one registered globally rather than inside a specific @WebSocket endpoint).

Common situations: Copy-pasting an endpoint-level @OnError method into a global error handler class; wanting the path value in a global handler without realizing it is unavailable.

Related errors


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