yewstack/yew · error · syn::Error

`break`, `continue`, and `return` in a match arm cannot be f

Error message

`break`, `continue`, and `return` in a match arm cannot be followed by HTML as their value. Wrap the arm body in braces, e.g. `_ => { return ::yew::html!(<span/>) }`.

What it means

Inside a `html!` match arm, `break`/`continue`/`return` are parsed as divergent control-flow trees; if HTML tokens follow such an expression in the same arm, the macro cannot give the arm a value and rejects it (html_match.rs:145-157). The help text shows the fix: wrap the arm body in braces and make the HTML an explicit `html!` call.

Source

Thrown at packages/yew-macro/src/html_tree/html_match.rs:153

            }
        }

        let comma: Option<Token![,]> = input.parse()?;

        // An unbraced `break`/`continue`/`return` body followed by more tokens
        // past the optional comma is almost always an attempt to give the
        // keyword an HTML value, which Rust does not accept as an expression.
        // Without this check the next-arm parser runs on the trailing `<...>`
        // and fails inside `Pat::parse` with a misleading "expected `>`".
        if comma.is_none() && !input.is_empty() {
            if let HtmlMatchArmBody::Unbraced { tree, .. } = &body {
                if matches!(
                    &**tree,
                    super::HtmlTree::Break(_)
                        | super::HtmlTree::Continue(_)
                        | super::HtmlTree::Return(_)
                ) {
                    return Err(syn::Error::new(
                        input.span(),
                        "`break`, `continue`, and `return` in a match arm cannot be followed by \
                         HTML as their value. Wrap the arm body in braces, e.g. `_ => { return \
                         ::yew::html!(<span/>) }`.",
                    ));
                }
            }
        }

        Ok(HtmlMatchArm {
            pat,
            guard,
            fat_arrow_token,
            body,
            comma,
        })
    }
}

View on GitHub (pinned to 0e4a05472f)

Solutions

  1. Wrap the arm body in braces with an explicit macro call, exactly as the help shows: `_ => { return ::yew::html!(<span/>) }`
  2. Move the early exit out of `html!`: bail or compute in plain Rust before invoking the macro
  3. Give the arm a real value (`None => <em/>`) instead of diverging mid-template

Example fix

// before
html! {
    match item {
        Some(i) => <li>{ i }</li>,
        None => return empty()
                 <li/>,
    }
}

// after
html! {
    match item {
        Some(i) => <li>{ i }</li>,
        None => { return ::yew::html!(<li/>) },
    }
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: An arm body like `None => return fallback() <li/>` — a `return`, `break`, or `continue` expression directly followed by more HTML tokens within the same match arm inside `html!`.

Common situations: Early-exit arms while rendering lists or guard clauses ('if none, bail out of the render'), or transplanting plain Rust match code that used `?`/`return` into an `html!` template.

Related errors


AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22). Data as JSON: /api/errors/80d41d2fddebcba1. Report an issue: GitHub.