leptos-rs/leptos · error

tried to use <A/> outside a <Router/>.

Error message

tried to use <A/> outside a <Router/>.

What it means

The `inner` render function of the `<A>` component reads `RouterContext` (for `current_url`) from context to compute whether the link is active. Without a `<Router>` ancestor the `expect` panics with "tried to use <A/> outside a <Router/>".

Source

Thrown at router/src/link.rs:132

    /// If `true`, the router will scroll to the top of the window at the end of navigation. Defaults to `true`.
    #[prop(default = true)]
    scroll: bool,
    /// The nodes or elements to be shown inside the link.
    children: Children,
) -> impl IntoView + 'static
where
    H: ToHref + Send + Sync + 'static,
{
    fn inner(
        href: ArcMemo<String>,
        target: Option<Oco<'static, str>>,
        exact: bool,
        children: Children,
        strict_trailing_slash: bool,
        scroll: bool,
    ) -> impl IntoView {
        let RouterContext { current_url, .. } =
            use_context().expect("tried to use <A/> outside a <Router/>.");
        let is_active = {
            let href = href.clone();
            move || {
                let path = normalize_path(&href.read());
                current_url.with(|loc| {
                    let loc = loc.path();
                    if exact {
                        loc == path
                    } else {
                        is_active_for(&path, loc, strict_trailing_slash)
                    }
                })
            }
        };

        view! {
            <a
                href=move || href.get()

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Render `<A>` inside the `<Router>` tree.
  2. Restructure layout so nav components are children of the router (or use root layout via router children).
  3. Use a plain `<a>` for links that don't require router-aware active state.

Example fix

// before
view! {
  <header><A href="/">Home</A></header>
  <Router><Routes/></Router>
}

// after
view! {
  <Router>
    <header><A href="/">Home</A></header>
    <Routes/>
  </Router>
}
Defensive patterns

Strategy: fallback

Validate before calling

let router_ok = use_context::<RouterContext>().is_some();
if !router_ok { /* render plain <a> instead of <A> */ }

Type guard

fn inside_router() -> bool { use_context::<RouterContext>().is_some() }

Prevention

When it happens

Trigger: Rendering `<A>` (or components wrapping it) outside `<Router>`; rendering `<A>` into a portal whose owner is outside the router; using `<A>` in tests without a router wrapper.

Common situations: Header/nav components hoisted above the router for layout reasons; dialog/modal portals mounted at document root; component libraries exporting link components used in non-router pages.

Related errors


AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01). Data as JSON: /api/errors/db25f61e57edd225. Report an issue: GitHub.