Errors
Errors are an inevitable fact of software development. SvelteKit handles errors differently depending on where they occur, what kind of errors they are, and the nature of the incoming request.
Error objects
SvelteKit distinguishes between expected and unexpected errors, both of which are represented as simple { status: number, message: string } objects by default.
You can add additional properties, like a code or a tracking id, as shown in the examples below. (When using TypeScript this requires you to redefine the Error type as described in type safety).
Expected errors
An expected error is one created with the error helper imported from @sveltejs/kit:
import { function error(status: number, body: Omit<App.Error, "status"> & {
status?: App.Error["status"];
}): never (+2 overloads)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError.
Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
error } from '@sveltejs/kit';
import * as module "$lib/server/database"db from '$lib/server/database';
/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>load({ params: Record<string, any>The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.
In the context of a remote function request initiated by the client, this relates to the page the remote function
was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine
whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.
params }) {
const const post: {
title: string;
content: string;
} | undefined
post = await module "$lib/server/database"db.function getPost(slug: string): Promise<{
title: string;
content: string;
} | undefined>
getPost(params: Record<string, any>The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.
In the context of a remote function request initiated by the client, this relates to the page the remote function
was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine
whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.
params.slug);
if (!const post: {
title: string;
content: string;
} | undefined
post) {
function error(status: number, body: {
status: number;
message: string;
} extends App.Error ? string | void | undefined : never): never (+2 overloads)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError.
Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, 'Not found');
}
return { post: {
title: string;
content: string;
}
post };
}import { function error(status: number, body: Omit<App.Error, "status"> & {
status?: App.Error["status"];
}): never (+2 overloads)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError.
Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
error } from '@sveltejs/kit';
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types';
export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.
In the context of a remote function request initiated by the client, this relates to the page the remote function
was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine
whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.
params }) => {
const const post: {
title: string;
content: string;
} | undefined
post = await module "$lib/server/database"db.function getPost(slug: string): Promise<{
title: string;
content: string;
} | undefined>
getPost(params: Record<string, any>The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.
In the context of a remote function request initiated by the client, this relates to the page the remote function
was called from, not the URL of the endpoint SvelteKit creates for the remote function. Never use this to determine
whether or not a user is authorized to access certain data, as these values are part of the request which could be manipulated.
params.slug);
if (!const post: {
title: string;
content: string;
} | undefined
post) {
function error(status: number, body: {
status: number;
message: string;
} extends App.Error ? string | void | undefined : never): never (+2 overloads)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError.
Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, 'Not found');
}
return { post: {
title: string;
content: string;
}
post };
};This throws an exception that SvelteKit catches, causing it to set the response status code to 404 and render an +error.svelte component, where the error is an App.Error object with the provided status and message.
<script>
let { error } = $props();
</script>
<h1>{error.message}</h1><script lang="ts">
let { error } = $props();
</script>
<h1>{error.message}</h1>You can add extra properties to the error object if needed:
function error(status: number, body: string, properties: {
status: number;
message: string;
} extends App.Error ? never : Omit<App.Error, "status" | "message">): never (+2 overloads)
Throws an error with a HTTP status code and an optional message.
When called during request handling, this will cause SvelteKit to
return an error response without invoking handleError.
Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
error(404, 'Not found', {
code: stringcode: 'NOT_FOUND'
});In SvelteKit 1.x you had to
throwtheerroryourself
Unexpected errors
An unexpected error is any other exception that occurs while handling a request. Since these can contain sensitive information, unexpected error messages and stack traces are not exposed to users.
By default, unexpected errors are printed to the console (or, in production, your server logs), while the error that is exposed to the user has a generic shape:
{ "status": 500, "message": "Internal Error" }Unexpected errors will go through the handleError hook, where you can add your own error handling — for example, sending errors to a reporting service, or returning a custom error object which becomes the error prop passed to +error.svelte.
You can override the HTTP status code used in the response by returning a status property:
// Assuming you have this ...
class class NotFoundNotFound extends var Error: ErrorConstructorError {}
/** @type {import('@sveltejs/kit').HandleServerError} */
export function function handleError(input: {
error: unknown;
event: RequestEvent;
status: number;
message: string;
}): MaybePromise<void | AppErrorWithOptionalStatus>
handleError({ error: unknownerror, event: RequestEvent<Record<string, string>, string | null>event, status: numberstatus, message: stringmessage }) {
// ... you can do this
if (error: unknownerror instanceof class NotFoundNotFound) {
return {
status?: number | undefinedstatus: 404,
message: stringmessage: 'Not found'
};
}
return { message: stringmessage: 'Something went wrong' };
}import type { type HandleServerError = (input: {
error: unknown;
event: RequestEvent;
status: number;
message: string;
}) => MaybePromise<void | AppErrorWithOptionalStatus>
The server-side handleError hook runs when an unexpected error is thrown while responding to a request.
If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event.
Make sure that this function never throws an error.
The returned object can include a status property to override the HTTP status code used in the response.
If omitted, the status defaults to 500.
HandleServerError } from '@sveltejs/kit';
// Assuming you have this ...
class class NotFoundNotFound extends var Error: ErrorConstructorError {}
export const const handleError: HandleServerErrorhandleError: type HandleServerError = (input: {
error: unknown;
event: RequestEvent;
status: number;
message: string;
}) => MaybePromise<void | AppErrorWithOptionalStatus>
The server-side handleError hook runs when an unexpected error is thrown while responding to a request.
If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event.
Make sure that this function never throws an error.
The returned object can include a status property to override the HTTP status code used in the response.
If omitted, the status defaults to 500.
HandleServerError = ({ error: unknownerror, event: RequestEvent<Record<string, string>, string | null>event, status: numberstatus, message: stringmessage }) => {
// ... you can do this
if (error: unknownerror instanceof class NotFoundNotFound) {
return {
status?: number | undefinedstatus: 404,
message: stringmessage: 'Not found'
};
}
return { message: stringmessage: 'Something went wrong' };
};Error boundaries
Errors that occur during load or rendering (for example inside a component's <script> block or template) bubble up to the nearest +error.svelte component. To handle errors at a more granular level, you can use a <svelte:boundary>:
<svelte:boundary>
...
{#snippet failed(error: App.Error)}
<!-- error went through the `handleError` hook and is of type `App.Error` -->
{error.message}
{/snippet}
</svelte:boundary>Responses
If an error occurs inside handle or inside a +server.js request handler, SvelteKit will respond with either a fallback error page or a JSON representation of the error object, depending on the request's Accept headers.
You can customise the fallback error page by adding a src/error.html file:
<!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 will replace %sveltekit.status% and %sveltekit.error.message% with their corresponding values.
If the error instead occurs inside a load function while rendering a page, SvelteKit will render the +error.svelte component nearest to where the error occurred. If the error occurs inside a load function in +layout(.server).js, the closest error boundary in the tree is an +error.svelte file above that layout (not next to it).
The exception is when the error occurs inside the root +layout.js or +layout.server.js, since the root layout would ordinarily contain the +error.svelte component. In this case, SvelteKit uses the fallback error page.
Type safety
If you're using TypeScript and need to customize the shape of errors, you can do so by declaring an App.Error interface in your app (by convention, in src/app.d.ts, though it can live anywhere that TypeScript can 'see'):
declare global {
namespace App {
interface interface App.ErrorDefines the common shape of expected and unexpected errors. Expected errors are thrown using the error function. Unexpected errors are handled by the handleError hooks which should return this shape.
Error {
App.Error.code: stringcode: string;
App.Error.id: stringid: string;
}
}
}
export {};This interface always includes status: number and message: string properties.
Further reading
Edit this page on GitHub llms.txt