SvelteKit provides a structured error handling system that distinguishes between expected errors (user-facing, like validation failures) and unexpected errors (bugs, infrastructure failures).

Expected Errors

Use error() from @sveltejs/kit to throw expected errors:

import { error } from '@sveltejs/kit'

export const load = async ({ params }) => {
  const post = await db.findPost(params.slug)
  if (!post) throw error(404, 'Post not found')
}

Expected errors are caught by the nearest +error.svelte and can include custom data.

Unexpected Errors

Unexpected errors (uncaught exceptions) are caught by handleError in hooks and the nearest +error.svelte. They should be logged on the server and a generic message shown to the user.

Error Pages

+error.svelte

Create per-route or app-level error pages:

<script>
  import { page } from '$app/stores'
</script>

<h1>{$page.status}: {$page.error?.message}</h1>
<p>Something went wrong.</p>
<a href="/">Go home</a>

Default Error Page

SvelteKit provides a default error page if no +error.svelte exists. Override it at the root layout level.

Error Boundaries

Use <svelte:boundary> for component-level error isolation:

<svelte:boundary onerror={(error, reset) => reset()}>
  <Widget />
</svelte:boundary>

This prevents a single component’s failure from crashing the entire page. The onerror callback provides the error and a reset function.

Redirects

Use redirect() from @sveltejs/kit to redirect during load functions and actions:

import { redirect } from '@sveltejs/kit'

export const load = async () => {
  throw redirect(302, '/login')
}

Common status codes:

  • 302 — temporary redirect
  • 303 — see other (after form submission)
  • 307 — temporary redirect (preserves method)
  • 308 — permanent redirect

Error Handling Layers

LayerPurpose
<svelte:boundary>Component-level error isolation
+error.svelteRoute-level error display
hooks.handleErrorGlobal error logging and sanitization
Fallback error pageCatch-all for unhandled route errors

See Also