quarkusio/quarkus · error · WebSocketClientException

Unable to obtain the path param for:

Error message

Unable to obtain the path param for: 

What it means

During connect, WebSocketConnectorBase.replacePathParameters() substitutes each {param} placeholder in the client endpoint path with values previously supplied via pathParam(). If a placeholder has no corresponding value in the pathParams map (value == null), this WebSocketClientException is thrown naming the missing parameter.

Source

Thrown at extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketConnectorBase.java:175

            String paramName = match.substring(1, match.length() - 1);
            names.add(paramName);
        }
        return names;
    }

    String replacePathParameters(String path) {
        if (path.isEmpty()) {
            return path;
        }
        StringBuilder sb = new StringBuilder();
        Matcher m = PATH_PARAM_PATTERN.matcher(path);
        while (m.find()) {
            // Replace {foo} with the param value
            String match = m.group();
            String paramName = match.substring(1, match.length() - 1);
            String val = pathParams.get(paramName);
            if (val == null) {
                throw new WebSocketClientException("Unable to obtain the path param for: " + paramName);
            }
            m.appendReplacement(sb, URLEncoder.encode(val, StandardCharsets.UTF_8));
        }
        m.appendTail(sb);
        return path.startsWith("/") ? sb.toString() : "/" + sb.toString();
    }

    protected WebSocketClientOptions populateClientOptions() {
        final WebSocketClientOptions clientOptions;
        if (customWebSocketClientOptions != null) {
            clientOptions = new WebSocketClientOptions(customWebSocketClientOptions);
        } else {
            clientOptions = new WebSocketClientOptions();
        }
        if (config.offerPerMessageCompression()) {
            clientOptions.setTryUsePerMessageCompression(true);
            if (config.compressionLevel().isPresent()) {
                clientOptions.setCompressionLevel(config.compressionLevel().getAsInt());

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call pathParam(name, value) for every placeholder in the endpoint path before connect()
  2. Compare the @WebSocketClient path placeholders against the pathParam() calls
  3. Set a default via pathParam() when the value may legitimately be absent

Example fix

// before
@WebSocketClient(path = "/chat/{roomId}")
connector.connect(); // missing roomId
// after
connector.pathParam("roomId", "42").connect();
Defensive patterns

Strategy: validation

Validate before calling

java.util.regex.Matcher m = java.util.regex.Pattern.compile("\\{([^}]+)}").matcher(endpointPath);
java.util.Set<String> required = new java.util.HashSet<>();
while (m.find()) required.add(m.group(1));
// ensure every required name was supplied via pathParam()

Try / catch

try {
    connector.connect();
} catch (WebSocketClientException e) {
    log.error("Missing path param; supply it with pathParam() before connect()", e);
}

Prevention

When it happens

Trigger: Connecting while the endpoint path contains a {placeholder} for which pathParam() was never called — e.g. forgetting a required param, building the path dynamically, or the annotation path was changed to add a new placeholder.

Common situations: Adding a new placeholder to the @WebSocketClient path without adding a matching pathParam() call in the connector; conditional logic that skips setting a param; config-driven paths.

Related errors


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