SvelteKit provides functions for creating HTTP errors, redirects, form failures, and validation errors to control application flow. These functions throw special error objects that SvelteKit catches and handles appropriately.
Throw an HTTP error with a status code to trigger error handling.
/**
* Throws an HttpError with the given status code and body
* @param status - HTTP status code (400-599)
* @param body - Optional error body with message and additional properties
* @throws {HttpError}
*/
function error(
status: number,
body?: { message: string; [key: string]: any }
): never;Usage Example:
import { error } from '@sveltejs/kit';
import type { RequestEvent } from '@sveltejs/kit';
export async function load({ params }: { params: { id: string } }) {
const post = await getPost(params.id);
if (!post) {
error(404, { message: 'Post not found' });
}
return { post };
}
// With additional error properties
export async function DELETE(event: RequestEvent) {
const item = await getItem(event.params.id);
if (item.protected) {
error(403, {
message: 'Cannot delete protected item',
reason: 'PROTECTED_RESOURCE'
});
}
}Check if an error is an HttpError, optionally with a specific status code.
/**
* Type guard to check if an error is an HttpError
* @param e - The error to check
* @param status - Optional specific status code to match
* @returns true if e is an HttpError (with matching status if provided)
*/
function isHttpError(e: unknown, status?: number): boolean;Usage Example:
import { isHttpError } from '@sveltejs/kit';
try {
await someOperation();
} catch (e) {
if (isHttpError(e)) {
console.log('HTTP error occurred:', e.status);
}
// Check for specific status
if (isHttpError(e, 404)) {
console.log('Resource not found');
}
}Throw a redirect to navigate to a different URL.
/**
* Throws a Redirect with the given status code and location
* @param status - Redirect status code (300-308, typically 303 or 307)
* @param location - Target URL as string or URL object
* @throws {Redirect}
*/
function redirect(status: number, location: string | URL): never;Usage Example:
import { redirect } from '@sveltejs/kit';
// Redirect after form submission (303 for POST-to-GET)
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
await saveData(data);
redirect(303, '/success');
}
};
// Redirect in load function (307 to preserve method)
export async function load({ locals }) {
if (!locals.user) {
redirect(307, '/login');
}
return { user: locals.user };
}
// Redirect to external URL
export async function GET() {
redirect(302, 'https://external-site.com/resource');
}Check if an error is a Redirect.
/**
* Type guard to check if an error is a Redirect
* @param e - The error to check
* @returns true if e is a Redirect
*/
function isRedirect(e: unknown): boolean;Usage Example:
import { isRedirect } from '@sveltejs/kit';
try {
await loadData();
} catch (e) {
if (isRedirect(e)) {
console.log('Redirect to:', e.location);
// Let SvelteKit handle the redirect
throw e;
}
// Handle other errors
}Create an ActionFailure to return validation errors or failure data from form actions.
/**
* Creates an ActionFailure for form submissions
* @param status - HTTP status code (400-599, typically 400)
* @param data - Optional failure data to return to client
* @returns ActionFailure object that SvelteKit handles specially
*/
function fail<T extends Record<string, any> | undefined>(
status: number,
data?: T
): ActionFailure<T>;Usage Example:
import { fail } from '@sveltejs/kit';
import type { Actions } from './$types';
export const actions = {
login: async ({ request }) => {
const data = await request.formData();
const email = data.get('email');
const password = data.get('password');
if (!email) {
return fail(400, {
email,
missing: true,
message: 'Email is required'
});
}
const user = await authenticate(email, password);
if (!user) {
return fail(401, {
email,
incorrect: true,
message: 'Invalid credentials'
});
}
return { success: true };
}
} satisfies Actions;Check if an error is an ActionFailure.
/**
* Type guard to check if an error is an ActionFailure
* @param e - The error to check
* @returns true if e is an ActionFailure
*/
function isActionFailure(e: unknown): boolean;Usage Example:
import { isActionFailure } from '@sveltejs/kit';
try {
const result = await performAction();
} catch (e) {
if (isActionFailure(e)) {
console.log('Action failed with status:', e.status);
console.log('Failure data:', e.data);
}
}Throw a validation error with detailed validation issues for imperatively failing form validation.
/**
* Throws a ValidationError with the given validation issues
* @param issues - Array of validation issues or simple string messages
* @throws {ValidationError}
* @since 2.47.3
*/
function invalid(...issues: (StandardSchemaV1.Issue | string)[]): never;Usage Example:
import { invalid } from '@sveltejs/kit';
import type { Actions } from './$types';
export const actions = {
register: async ({ request }) => {
const data = await request.formData();
const email = data.get('email');
const age = data.get('age');
const issues = [];
if (!email || !email.includes('@')) {
issues.push({
path: ['email'],
message: 'Valid email is required'
});
}
if (!age || parseInt(age) < 18) {
issues.push({
path: ['age'],
message: 'Must be 18 or older'
});
}
if (issues.length > 0) {
invalid(...issues);
}
// Continue with registration
},
// Simple string messages (no path)
login: async ({ request }) => {
const data = await request.formData();
const username = data.get('username');
const password = data.get('password');
const success = await tryLogin(username, password);
if (!success) {
invalid('Incorrect username or password');
}
// Continue with login
}
} satisfies Actions;Check if an error is a ValidationError.
/**
* Type guard to check if an error is a ValidationError
* @param e - The error to check
* @returns true if e is a ValidationError
* @since 2.47.3
*/
function isValidationError(e: unknown): boolean;Usage Example:
import { isValidationError } from '@sveltejs/kit';
try {
await validateAndProcess();
} catch (e) {
if (isValidationError(e)) {
console.log('Validation failed with issues:', e.issues);
e.issues.forEach(issue => {
console.log(`Field ${issue.path.join('.')}: ${issue.message}`);
});
}
}interface HttpError {
status: number;
body: { message: string; [key: string]: any };
}
interface Redirect {
status: number;
location: string;
}
interface ActionFailure<T extends Record<string, any> | undefined = Record<string, any> | undefined> {
status: number;
data: T;
}
interface ValidationError {
issues: StandardSchemaV1.Issue[];
}
/**
* Standard Schema V1 validation issue format
* From @standard-schema/spec package
*/
interface StandardSchemaV1.Issue {
message: string;
path?: (string | number)[];
}error, redirect, invalid) have return type never because they always throwerror() in load functions, request handlers, and hooksredirect() for navigation after successful operations (303) or access control (307)fail() in form actions to return validation errors without throwinginvalid() in form actions for declarative validation with detailed error paths