leptos-rs/leptos · error

You cannot call `use_navigate` outside a <Router>.

Error message

You cannot call `use_navigate` outside a <Router>.

What it means

use_navigate requires routing context that only exists inside a <Router> component. Calling it outside — e.g. in a top-level module, plain function, or component rendered above the Router — panics because the navigation handle cannot be found in context.

Source

Thrown at router/src/hooks.rs:277

        }
    })
}

/// Returns a function that can be used to navigate to a new route.
///
/// This should only be called on the client; it does nothing during
/// server rendering.
///
/// ```rust
/// # if false { // can't actually navigate, no <Router/>
/// let navigate = leptos_router::hooks::use_navigate();
/// navigate("/", Default::default());
/// # }
/// ```
#[track_caller]
pub fn use_navigate() -> impl Fn(&str, NavigateOptions) + Clone {
    let cx = use_context::<RouterContext>()
        .expect("You cannot call `use_navigate` outside a <Router>.");
    move |path: &str, options: NavigateOptions| cx.navigate(path, options)
}

/// Returns a reactive string that contains the route that was matched for
/// this [`Route`](crate::components::Route).
#[track_caller]
pub fn use_matched() -> Memo<String> {
    use_context::<Matched>()
        .expect("use_matched called outside a matched Route")
        .0
        .into()
}

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Move the component or function that calls `use_navigate()` inside the `<Router>` tree.
  2. For programmatic navigation outside components, restructure to trigger navigation from within the router tree (e.g. a signal consumed by an in-router component), or use the `redirect` mechanism available in that context.
  3. In tests, wrap with a MemoryRouter-based `<Router>`.

Example fix

// before
fn logout() {
    let navigate = use_navigate(); // panics: called in a module fn outside tree
    navigate("/login", Default::default());
}

// after
#[component]
fn LogoutButton() -> impl IntoView {
    let navigate = use_navigate();
    view! { <button on:click=move |_| navigate("/login", Default::default())>Logout</button> }
}
Defensive patterns

Strategy: fallback

Validate before calling

// Inside a component, verify context before navigating:
let navigate_fn = use_context::<RouterContext>().map(|cx| move |p: &str| cx.navigate(p, Default::default()));

Type guard

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

Prevention

When it happens

Trigger: Calling `use_navigate()` in a component outside the `<Router>` tree (e.g. a login page or toast rendered above the router), in event handlers set up before the router mounts, or in tests without a router wrapper.

Common situations: Redirect-on-auth logic placed outside the router; navigation helpers called from global event listeners; storybook/test setups rendering components standalone.

Related errors


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