DioxusLabs/dioxus · error · syn::Error
expected at most one '?'
Error message
expected at most one '?'
What it means
RouteParser::new splits the route literal on `?` and requires at most two parts (path, query). More than one `?` means the string is malformed — the second `?` would end up inside the query section and produce nonsense, so it is rejected up front (packages/fullstack-macro/src/lib.rs:975-979).
Source
Thrown at packages/fullstack-macro/src/lib.rs:981
url_without_queries
);
Some(full_url)
}
}
struct RouteParser {
path_params: Vec<(Slash, PathParam)>,
query_params: Vec<QueryParam>,
}
impl RouteParser {
fn new(lit: LitStr) -> syn::Result<Self> {
let val = lit.value();
let span = lit.span();
let split_route = val.split('?').collect::<Vec<_>>();
if split_route.len() > 2 {
return Err(syn::Error::new(span, "expected at most one '?'"));
}
let path = split_route[0];
if !path.starts_with('/') {
return Err(syn::Error::new(span, "expected path to start with '/'"));
}
let path = path.strip_prefix('/').unwrap();
let mut path_params = Vec::new();
for path_param in path.split('/') {
path_params.push((
Slash(span),
PathParam::new(path_param, span, Box::new(parse_quote!(())))?,
));
}
let path_param_len = path_params.len();View on GitHub (pinned to 393d190a80)
Solutions
- Keep exactly one `?` between path and query: `/search?q&other`.
- If a query value may contain `?`, it must be percent-encoded by the client (`%3F`) — never place a raw `?` in the route literal.
- Delete the stray `?` produced by string concatenation and use `&` between query params.
Example fix
// before
#[route(GET, "/search?q=?other")]
async fn search(q: String, other: String) { ... }
// after
#[route(GET, "/search?q&other")]
async fn search(q: String, other: String) { ... } Defensive patterns
Strategy: validation
Validate before calling
fn validate_route(route: &str) -> Result<(), String> {
if route.split('?').count() > 2 {
return Err(format!("expected at most one '?': {route}"));
}
Ok(())
}
// Unit-test every route constant/string before committing:
#[test]
fn routes_well_formed() { for r in ["/items/{id}", "/search?q"] { validate_route(r).unwrap(); } } Prevention
- Treat '?' as structural: exactly one separator, '&' between query keys, never data.
- Percent-encode any literal '?' inside values (%3F) on the client side.
When it happens
Trigger: `#[route(GET, "/search?q=?other")]`; a query value containing a literal `?` such as `?q=a?b`; accidentally concatenating two route strings that each had their own query, e.g. `"/list?sort" + "&?page"`.
Common situations: Building route strings dynamically at authoring time; copying a URL with an embedded `?` from a browser address bar; misunderstanding that `?` is a structural separator here, not data.
Related errors
- Use `api_route` instead of `route` to use OpenAPI options
- path parameter `{}` not found in function arguments
- query parameter `{}` not found in function arguments
- Cannot have multiple query parameters when one is a catch-al
- HTTP method specified both in macro and in attribute
AI-assisted analysis of DioxusLabs/dioxus@393d190a80 (2026-08-16).
Data as JSON: /api/errors/8f60839210734914.
Report an issue: GitHub.