Using SvelteKit Hooks: handle, handleError, and handleFetch
📖 Scenario: You are building a simple SvelteKit app that fetches user data from an API. You want to add hooks to manage requests, handle errors gracefully, and modify fetch calls globally.
🎯 Goal: Build a SvelteKit hooks.server.js file that implements handle to log requests, handleError to catch and log errors, and handleFetch to add a custom header to all fetch requests.
📋 What You'll Learn
Create a handle hook that logs the request method and URL
Add a handleError hook that logs errors and returns a custom message
Implement a handleFetch hook that adds a X-Custom-Header to all fetch requests
💡 Why This Matters
🌍 Real World
Hooks in SvelteKit let you control how requests and errors are handled globally, which is useful for logging, authentication, and modifying fetch calls in real apps.
💼 Career
Understanding hooks is important for building robust SvelteKit applications that handle errors and requests cleanly, a common requirement in professional web development.
Progress0 / 4 steps
1
Create the handle hook to log requests
Create a handle function in hooks.server.js that takes { event, resolve } as parameters. Inside, log the request method and URL using console.log. Then return the result of calling resolve(event).
Svelte
Hint
Use console.log to print the request method and URL from event.request.method and event.url.
2
Add the handleError hook to log errors
Add an async handleError function in hooks.server.js that takes { error, event } as parameters. Inside, log the error message with console.error. Return an object with message set to 'An unexpected error occurred'.
Svelte
Hint
Use console.error to log the error message from error.message. Return an object with a friendly message.
3
Implement the handleFetch hook to add a custom header
Add an async handleFetch function in hooks.server.js that takes { request, fetch } as parameters. Clone the request and add a header X-Custom-Header with value MyHeaderValue. Use the modified request with fetch and return the response.
Svelte
Hint
Create a new Request object copying the original, then add the header with headers.set.
4
Complete the hooks.server.js with all hooks combined
Ensure your hooks.server.js file exports all three hooks: handle, handleError, and handleFetch with the exact implementations from previous steps.
Svelte
Hint
Make sure all three functions are exported and present in the file.
Practice
(1/5)
1. What is the main purpose of the handle hook in SvelteKit?
easy
A. To catch and handle errors during server-side rendering
B. To define client-side event handlers for UI elements
C. To intercept and modify fetch requests made by the app
D. To manage and modify incoming requests and outgoing responses
Solution
Step 1: Understand the role of handle hook
The handle hook runs on every request and can modify the request or response.
Step 2: Compare with other hooks
handleError is for errors, handleFetch is for fetch interception, so they don't manage requests/responses directly.
Final Answer:
To manage and modify incoming requests and outgoing responses -> Option D
A. Cannot modify headers on the response object directly; it is immutable
B. Missing await before resolve(event)
C. Incorrect parameter names; should be { request, resolve }
D. handle hook must be synchronous, not async
Solution
Step 1: Check response header modification
The response object is immutable; headers cannot be set directly on it.
Step 2: Confirm other parts are correct
Await is used correctly, parameter names are valid, and handle can be async.
Final Answer:
Cannot modify headers on the response object directly; it is immutable -> Option A
Quick Check:
Response headers are immutable [OK]
Hint: Response headers are immutable; clone before modifying [OK]
Common Mistakes:
Trying to set headers directly on response
Confusing parameter names
Thinking handle must be synchronous
5. You want to add a custom header X-User with the username from event.locals.user to every fetch request made by your app. Which handleFetch hook implementation correctly achieves this?
hard
A. export async function handleFetch({ request, fetch }) {
request.headers.set('X-User', event.locals.user);
return fetch(request);
}
B. export async function handleFetch({ request, fetch, event }) {
const modifiedRequest = new Request(request, {
headers: { ...Object.fromEntries(request.headers), 'X-User': event.locals.user }
});
return fetch(modifiedRequest);
}
C. export async function handleFetch({ request, fetch, event }) {
request.headers.append('X-User', event.locals.user);
return fetch(request);
}
D. export async function handleFetch({ request, fetch, event }) {
const headers = new Headers(request.headers);
headers.set('X-User', event.locals.user);
const modifiedRequest = new Request(request.url, { method: request.method, headers });
return fetch(modifiedRequest);
}
Solution
Step 1: Understand immutability of request headers
Request headers are immutable; to modify them, create a new Request with new headers while preserving other properties like body.
Step 2: Analyze the correct implementation
The code that uses new Request(request, { headers: { ...Object.fromEntries(request.headers), 'X-User': event.locals.user } }) clones the original request fully (including body, method, etc.) and overrides the headers correctly.
Step 3: Identify errors in other options
Directly modifying request.headers with set or append fails because headers are immutable. Creating a new Request with only url, method, and headers omits the body and other request properties.
Final Answer:
export async function handleFetch({ request, fetch, event }) {
const modifiedRequest = new Request(request, {
headers: { ...Object.fromEntries(request.headers), 'X-User': event.locals.user }
});
return fetch(modifiedRequest);
} -> Option B
Quick Check:
new Request(request, { headers: ... }) clones fully [OK]
Hint: Clone request with new Request(request, { headers: updated }) [OK]
Common Mistakes:
Modifying headers directly on original request
Not cloning request before changing headers
Omitting request body when recreating Request
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.