sveltejs/kit · error
Cannot call ${caller}(...) before router is initialized
Error message
Cannot call ${caller}(...) before router is initialized What it means
update_state() backs goto(), pushState() and replaceState(). If the router has not started yet (the `started` flag is false, DEV only), calling any of these throws because there is no router state to update. Navigation APIs are only valid after hydration/initialization completes.
Source
Thrown at packages/kit/src/runtime/client/client.js:2968
intent,
state,
{ replace: true, persist_state: false, reset: false },
'replaceState'
);
}
/**
* @param {NavigationIntent} intent
* @param {App.PageState} state
* @param {{ replace: boolean; persist_state: boolean; reset: boolean; }} options
* @param {'goto' | 'pushState' | 'replaceState'} caller
*/
async function update_state(intent, state, { replace, persist_state, reset }, caller) {
const url = intent.url;
const previous_snapshot_registrations = current_registrations();
if (DEV && !started) {
throw new Error(`Cannot call ${caller}(...) before router is initialized`);
}
const nav =
// For backwards compatibility we don't trigger navigation hooks etc for push/replaceState
caller === 'goto' ? _before_navigate({ url, type: 'goto', intent, shallow: true }) : undefined;
if (!nav && caller === 'goto') return;
const nav_token = {};
if (nav) {
navigation_token = invalidation_token = nav_token;
is_navigating = true;
set_navigation(nav.navigation);
updating = true;
}
if (replace) {View on GitHub (pinned to 03f1687fe6)
Solutions
- Move the call into onMount or after the app/router has started
- Use $app/stores page state instead of navigating during init
- Gate the call on the router being ready (e.g. afterMount flag)
Example fix
// before
// +page.svelte module scope
const id = page.params.id;
if (!id) goto('/');
// after
import { onMount } from 'svelte';
onMount(() => { if (!page.params.id) goto('/'); }); Defensive patterns
Strategy: validation
Validate before calling
let routerReady = false;
// set routerReady = true in onMount of your root layout
function safeGoto(...args) {
if (!routerReady) return;
return goto(...args);
} Try / catch
try { await goto('/'); } catch (e) { if (e.message.includes('before router is initialized')) { /* defer */ } else { throw e; } } Prevention
- Never navigate at module top level
- Defer navigation to onMount or event handlers
- Guard redirects-from-init logic with a readiness flag
When it happens
Trigger: Calling goto/pushState/replaceState at module top level of a +page.svelte or in a store initializer that runs before the client router starts; calling during SSR-adjacent early module evaluation.
Common situations: Top-level side effects in components; initializing state from a URL in module scope; invoking navigation from imported module bodies rather than lifecycle callbacks.
Related errors
- Cannot add tasks to a queue that has ended
- Can only disable scroll handling during navigation
- DEV: Cannot use `${caller}` with an external URL. Use `windo
- DEV: Cannot use `${caller}` with a URL that does not resolve
- The `goto(..., { noScroll: true, keepFocus: true })` options
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/14748c4974983965.
Report an issue: GitHub.