Overview

GlobalErrorHandler wraps your app and catches all unhandled errors (window.error and unhandledrejection). On catch it runs your chosen recovery strategy and optionally renders a full-page error UI. SessionStorage-based loop prevention stops the strategy from running away.

⚠️ Breaking change in v5.2.0: the built-in error toast was removed entirely. The showToast config field is gone. Notification UI is now your responsibility — wire your favorite toast library inside the onError callback. See below for the migration recipe.

Quick Start

1. Configure in main.js

Configure in main.js
 

2. Wrap your app with GlobalErrorHandler

GlobalErrorHandler is a wrapper — pass your app content as children, not as a sibling.

App.svelte
 

Recovery strategies

navigateSafe — navigate to a known-good route (default)

Pushes safeRoute when an error fires. Best for most apps with a reliable landing page.

 

restart — full app reload

Hard-refreshes the page. Useful when errors are likely due to corrupted in-memory state. The autoRestart + restartDelay options control whether the reload is automatic or user-triggered.

 

showError — full-page error UI

Renders the error component (built-in ErrorDisplay by default, or your own via the errorComponent snippet prop on GlobalErrorHandler). The user picks their own recovery path.

 

custom — run your own recovery

The router catches the error, then hands it to your onRecover callback with helpers for restart / navigate / show-error so you can decide what to do.

 

⚠️ showToast removed in v5.2.0

Previously the library rendered a built-in <div class="error-toast"> on caught errors, gated by showToast (default true). The render guard was broken under the default navigateSafe strategy: it called clearError() synchronously after push() in the same handler tick, so by the time Svelte's reactive system flushed toastVisible = true, the error state was already gone and the toast never rendered.

Rather than patch the broken interaction, the toast was removed. Every app already has a preferred toast/snackbar library — the router's job is to surface the event, not paint pixels.

Migration from showToast
 

TypeScript will flag the now-unknown property, so a typecheck after upgrade is the easiest way to find every call site that needs updating.

Configuration options

OptionTypeDefaultDescription
strategy'navigateSafe' | 'restart' | 'showError' | 'custom''navigateSafe'Recovery behavior on caught error
safeRoutestring'/'Used by navigateSafe strategy
maxRestartsnumber3Max restarts allowed within restartWindow
restartWindownumber (ms)60000Sliding window for counting restarts
autoRestartbooleanfalseWhen strategy: 'restart', restart automatically vs wait for user
restartDelaynumber (ms)5000Delay before auto-restart fires
showErrorComponentbooleanfalseRender the full-page error UI when an error is active
onError(error, errorInfo, context) => voidLogging / monitoring hook. Fires on every catch, independent of strategy. This is where your toast library goes.
onRecover(error, errorInfo, context, helpers) => voidRecovery callback. Only fires when strategy: 'custom'.
ignoreErrors(RegExp | string)[][]Errors matching any pattern are silently dropped (no onError, no recovery)
isDevelopmentbooleanfalseDefault ErrorDisplay shows stack traces only when true

Filtering noisy errors with ignoreErrors

Pass an array of patterns. Matching errors never reach onError or the recovery strategy — they're treated as if they hadn't been thrown.

Common ignore patterns
 

Restart loop prevention

When an error keeps firing during recovery (e.g. a broken initialization that breaks safeRoute too), the restart counter prevents infinite loops. Counts live in sessionStorage under __svelte_spa_router_restart_count and expire after restartWindow.

 

The counter resets when:

  • The user navigates without an error
  • The browser tab is closed (sessionStorage scope)
  • The window passes without new restarts

Helper functions

All exported from @keenmate/svelte-spa-router/helpers/error-handler. Inside onRecover, the same helpers are passed as the helpers argument.

restart()

Trigger a restart, respecting maxRestarts. Returns true if it actually restarted, false if rate-limited.

 

navigate(route)

Navigate to any route. Takes a path string argument (unlike safeRoute, which is configured once).

 

showError()

Force the full-page error UI to render (assumes showErrorComponent: true is configured).

canRestart() / getRestartCount()

Inspect the restart state — useful for gating a "Try again" button in your custom error component.

 

Custom error UI via errorComponent snippet

Pass an errorComponent snippet to GlobalErrorHandler. The snippet receives an ErrorComponentProps argument with the error, the error info, and recovery callbacks bound to the configured strategy.

Custom error UI
 

Snippet props (ErrorComponentProps): error, errorInfo, onRestart, onNavigateSafe, onContinue, canRestart.

Integration with error tracking

Sentry

 

Analytics + toast

 

Best practices

Pick the right strategy

  • navigateSafe — most apps with a reliable home page
  • restart — stale-state issues that a reload would fix
  • showError — dev mode, or when you want users to choose recovery
  • custom — branching recovery logic (e.g. different routes per error type)

Don't conflate logging and recovery

onError is for monitoring / toasts / analytics — fires on every catch regardless of strategy. onRecover is only for the custom strategy and decides what happens. Keep them separate.

Always wrap with GlobalErrorHandler

If your app content isn't inside <GlobalErrorHandler>, errors won't be caught. Wrapping at the root means it covers every route.

Filter known-noisy errors

ResizeObserver loop and AbortError are textbook examples — neither is a real bug, both will trigger recovery if you don't ignore them.

Troubleshooting

Errors aren't being caught

  • Verify your app content is inside <GlobalErrorHandler> (not a sibling)
  • Check ignoreErrors — is the pattern accidentally matching the error you care about?
  • Confirm configureGlobalErrorHandler ran before mount(App, …)

onRecover never fires

 

Restart loop never stops

  • Lower maxRestarts (e.g. 2)
  • Clear sessionStorage manually during debugging: delete sessionStorage.__svelte_spa_router_restart_count
  • If the error fires on every route (including safeRoute), navigateSafe can't recover — switch to showError so the user can act