quarkusio/quarkus · error · WebSocketServerException
Path parameter may not be followed by an alphanumeric chara
Error message
Path parameter may not be followed by an alphanumeric character or underscore:
What it means
WebSocket path templates use {param} placeholders which are rewritten to :param routing patterns. A placeholder may not be immediately followed by a letter, digit, or underscore, because the generated pattern would become ambiguous/unparseable. The build fails with WebSocketServerException naming the offending path.
Source
Thrown at extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/WebSocketProcessor.java:1040
path = "/" + path;
}
return prefix + path;
}
static String getPath(String path) {
if (path.isEmpty()) {
return path;
}
StringBuilder sb = new StringBuilder();
Matcher m = PATH_PARAM_PATTERN.matcher(path);
while (m.find()) {
// Replace {foo} with :foo
String match = m.group();
int end = m.end();
if (end < path.length()) {
char nextChar = path.charAt(end);
if (Character.isAlphabetic(nextChar) || Character.isDigit(nextChar) || nextChar == '_') {
throw new WebSocketServerException("Path parameter " + match
+ " may not be followed by an alphanumeric character or underscore: " + path);
}
}
m.appendReplacement(sb, ":" + match.subSequence(1, match.length() - 1));
}
m.appendTail(sb);
return path.startsWith("/") ? sb.toString() : "/" + sb.toString();
}
public static String getOriginalPath(String path) {
StringBuilder sb = new StringBuilder();
Matcher m = TRANSLATED_PATH_PARAM_PATTERN.matcher(path);
while (m.find()) {
// Replace :foo with {foo}
String match = m.group();
m.appendReplacement(sb, "{" + match.subSequence(1, match.length()) + "}");
}
m.appendTail(sb);View on GitHub (pinned to e1c734241f)
Solutions
- Insert a separator between the placeholder and any following literal: '/', '-', or '.' (e.g. {id}/x, {id}-detail).
- Rewrite the path so placeholders occupy whole segments.
- If a literal must touch the parameter, move the literal into the handler or use a different path design.
Example fix
// before
@WebSocket(path = "/users/{id}x")
// after
@WebSocket(path = "/users/{id}/x") Defensive patterns
Strategy: validation
Validate before calling
// Validate the path before annotating: no '{...}' followed by [A-Za-z0-9_]
static boolean isValidWsPath(String path) {
return path == null || !java.util.regex.Pattern.compile("\\{[^}]+\\}[A-Za-z0-9_]").matcher(path).find();
} Prevention
- Keep each {param} as a whole path segment
- Follow placeholders only with '/', '-', or '.' literals
- Write a unit test asserting endpoint path patterns
- Beware translating path syntax from frameworks allowing {id}suffix
When it happens
Trigger: Declaring @WebSocket(path = ...) where a '{param}' segment is directly followed by an alphanumeric or '_' character, e.g. path = "/users/{id}x" or "/files/{name}_backup". The regex-match loop in path conversion detects the bad following character.
Common situations: Appending a literal suffix right after a placeholder without a separator; typos when writing REST-like paths; converting existing route definitions from frameworks with different path syntax.
Related errors
- ${class} has to be an interface
- Specified path can not be empty
- GeneratedStaticResourceBuildItem endpoint must start with '/
- GeneratedStaticResourceBuildItem endpoint must not end with
- Unable to inject @%s callback parameter '%s' declared on %s:
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/7554fbf901e30296.
Report an issue: GitHub.