DioxusLabs/dioxus · error · syn::Error

expected path param to be wrapped in curly braces

Error message

expected path param to be wrapped in curly braces

What it means

PathParam::new treats a segment starting with `{` as a capture and requires a matching closing `}`. If the opening brace has no suffix brace, the segment is neither valid capture nor static text, so it is rejected (packages/fullstack-macro/src/lib.rs:1102-1110).

Source

Thrown at packages/fullstack-macro/src/lib.rs:1109

        matches!(self, Self::Capture(..) | Self::WildCard(..))
    }

    fn capture(&self) -> Option<(&Ident, &Type)> {
        match self {
            Self::Capture(_, _, ident, ty, _) => Some((ident, ty)),
            Self::WildCard(_, _, _, ident, ty, _) => Some((ident, ty)),
            _ => None,
        }
    }

    fn new(str: &str, span: Span, ty: Box<Type>) -> syn::Result<Self> {
        let ok = if str.starts_with('{') {
            let str = str
                .strip_prefix('{')
                .unwrap()
                .strip_suffix('}')
                .ok_or_else(|| {
                    syn::Error::new(span, "expected path param to be wrapped in curly braces")
                })?;
            Self::Capture(
                LitStr::new(str, span),
                Brace(span),
                Ident::new(str, span),
                ty,
                Brace(span),
            )
        } else if str.starts_with('*') && str.len() > 1 {
            let str = str.strip_prefix('*').unwrap();
            Self::WildCard(
                LitStr::new(str, span),
                Brace(span),
                Star(span),
                Ident::new(str, span),
                ty,
                Brace(span),
            )

View on GitHub (pinned to 393d190a80)

Solutions

  1. Balance the braces: `/blog/{id}`.
  2. If you need a literal `{` or `}` in a static segment, percent-encode or choose different static text — braces are reserved for captures.
  3. Re-read each capture as `{ident}` exactly one identifier, nothing else inside.

Example fix

// before
#[route(GET, "/blog/{id")]
async fn blog(id: i32) { ... }

// after
#[route(GET, "/blog/{id}")]
async fn blog(id: i32) { ... }
Defensive patterns

Strategy: validation

Validate before calling

fn validate_route(route: &str) -> Result<(), String> {
    let path = route.split('?').next().unwrap();
    for seg in path.trim_start_matches('/').split('/') {
        if seg.starts_with('{') && !seg.ends_with('}') {
            return Err(format!("unbalanced '{{' in segment {seg:?} of {route}"));
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: `#[route(GET, "/blog/{id")]`; `/user/{id}}` style typos (unbalanced braces); segments like `/{a{b}` where inner braces confuse the pairing; JSON-template leftovers such as `/{id}` being edited down to `/{id`.

Common situations: Hand-editing route strings and dropping a brace; generating routes from templating systems that strip characters; pasting from docs where markdown mangled the braces.

Related errors


AI-assisted analysis of DioxusLabs/dioxus@393d190a80 (2026-08-16). Data as JSON: /api/errors/cd6a5679c80117f6. Report an issue: GitHub.