Skip to main content
Errors are inevitable in software development. SvelteKit handles errors differently depending on where they occur and what kind they are.

Error objects

SvelteKit distinguishes between expected and unexpected errors, both represented as simple { message: string } objects by default.
You can add additional properties like code or tracking id by customizing the App.Error type.

Expected errors

An expected error is created with the error helper from @sveltejs/kit:
src/routes/blog/[slug]/+page.server.js
import { error } from '@sveltejs/kit';
import * as db from '$lib/server/database';

export async function load({ params }) {
	const post = await db.getPost(params.slug);

	if (!post) {
		error(404, {
			message: 'Not found'
		});
	}

	return { post };
}
This causes SvelteKit to:
1

Set the response status

Sets the HTTP status code to 404
2

Render error page

Renders the nearest +error.svelte component
3

Pass error object

Makes the error object available as page.error

Displaying errors

src/routes/+error.svelte
<script>
	import { page } from '$app/state';
</script>

<h1>{page.error.message}</h1>

Adding custom properties

declare global {
	namespace App {
		interface Error {
			message: string;
			code: string;
		}
	}
}

export {};

Shorthand syntax

For convenience, pass a string as the second argument:
error(404, 'Not found');

Unexpected errors

An unexpected error is any other exception that occurs while handling a request. These can contain sensitive information, so messages and stack traces are not exposed to users.
By default, unexpected errors are printed to the console but show a generic message to users:
{ "message": "Internal Error" }

handleError hook

Unexpected errors go through the handleError hook, where you can:
src/hooks.server.js
import * as Sentry from '@sentry/sveltekit';

Sentry.init({/*...*/})

export async function handleError({ error, event, status, message }) {
  const errorId = crypto.randomUUID();
  
  Sentry.captureException(error, {
    extra: { event, errorId, status }
  });
  
  return {
    message: 'Whoops!',
    errorId
  };
}
src/hooks.server.js
export async function handleError({ error, event, status, message }) {
  // Extract safe information
  const errorId = crypto.randomUUID();
  
  return {
    message: 'An error occurred',
    errorId,
    timestamp: new Date().toISOString()
  };
}
src/hooks.client.js
export async function handleError({ error, event, status, message }) {
  console.error('Client error:', error);
  
  return {
    message: 'Something went wrong',
    code: 'CLIENT_ERROR'
  };
}
Make sure that handleError never throws an error itself.

Error responses

How SvelteKit responds to errors depends on where they occur:

In handle or +server.js

SvelteKit responds with either:
  • Fallback error page (if Accept header expects HTML)
  • JSON representation (if Accept header is application/json)

Custom fallback page

Create src/error.html to customize the fallback error page:
src/error.html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>%sveltekit.error.message%</title>
	</head>
	<body>
		<h1>My custom error page</h1>
		<p>Status: %sveltekit.status%</p>
		<p>Message: %sveltekit.error.message%</p>
	</body>
</html>
SvelteKit replaces these placeholders:
  • %sveltekit.status% → HTTP status code
  • %sveltekit.error.message% → Error message

In load functions

If an error occurs inside a load function, SvelteKit renders the nearest +error.svelte component.
  • Errors in +page.server.js or +page.js render the nearest sibling +error.svelte
  • Errors in +layout.server.js or +layout.js render the nearest parent +error.svelte (not the sibling)
  • Errors in root +layout.js or +layout.server.js use the fallback error page

Type safety

Customize the shape of errors with TypeScript:
src/app.d.ts
declare global {
	namespace App {
		interface Error {
			code: string;
			id: string;
		}
	}
}

export {};
The App.Error interface always includes a message: string property.

Error helper reference

From @sveltejs/kit:
error
function
Throws an HTTP error with a status code and message
import { error } from '@sveltejs/kit';

error(404, 'Not found');
error(403, { message: 'Forbidden', code: 'ACCESS_DENIED' });
isHttpError
function
Checks if an error was thrown by the error helper
import { isHttpError } from '@sveltejs/kit';

try {
  // ...
} catch (e) {
  if (isHttpError(e, 404)) {
    // Handle 404 specifically
  }
}

Common patterns

import { error } from '@sveltejs/kit';

export async function load({ locals }) {
	if (!locals.user) {
		error(401, 'Not logged in');
	}
	
	if (!locals.user.isAdmin) {
		error(403, 'Not an admin');
	}
}

Learn more

Follow the interactive tutorial on errors and redirects