leptos-rs/leptos · error

called use_resolved_path outside a <Router>

Error message

called use_resolved_path outside a <Router>

What it means

`use_resolved_path` is a crate-internal hook used by `<A>` and `<Form>` that pulls `RouterContext` to resolve a path relative to the current route. It panics when no `<Router>` ancestor provides that context.

Source

Thrown at router/src/hooks.rs:245

#[track_caller]
pub fn use_query<T>() -> Memo<Result<T, ParamsError>>
where
    T: Params + PartialEq + Send + Sync + 'static,
{
    let url = use_url_raw();
    Memo::new(move |_| url.with(|url| T::from_map(url.search_params())))
}

#[derive(Debug, Clone)]
pub(crate) struct Matched(pub ArcMemo<String>);

/// Resolves the given path relative to the current route.
#[track_caller]
pub(crate) fn use_resolved_path(
    path: impl Fn() -> String + Send + Sync + 'static,
) -> ArcMemo<String> {
    let router = use_context::<RouterContext>()
        .expect("called use_resolved_path outside a <Router>");
    // TODO make this work with flat routes too?
    let matched = use_context::<Matched>().map(|n| n.0);
    ArcMemo::new(move |_| {
        let path = path();
        if path.starts_with('/') {
            path
        } else {
            router
                .resolve_path(
                    &path,
                    matched.as_ref().map(|n| n.get()).as_deref(),
                )
                .to_string()
        }
    })
}

/// Returns a function that can be used to navigate to a new route.

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Render the `<A>`/`<Form>` component inside the `<Router>` tree.
  2. Restructure so navigation components are children of the router, or use plain `<a>` tags for static links that don't need routing.
  3. In tests, wrap the component under test in a `<Router>`.

Example fix

// before
view! {
  <A href="/about">About</A>
  <Router><Routes/></Router>
}

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

Strategy: fallback

Validate before calling

let has_router = use_context::<RouterContext>().is_some();
if !has_router { return view! { <a href={path}>{children}</a> }.into_any(); }

Type guard

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

Prevention

When it happens

Trigger: Rendering `<A href=...>` or `<Form ...>` outside a `<Router>`; calling the internal hook from custom components used above the router; portals rendering links outside the router owner.

Common situations: A shared Link component rendered in a modal or root layout outside the router; test harnesses without `<Router>`; migrating an app and moving the router so links end up above it in the tree.

Related errors


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