Bird
Raised Fist0
Svelteframework~10 mins

Hooks (handle, handleError, handleFetch) in Svelte - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Hooks (handle, handleFetch, handleError)
Request received
↓
handle hook runs
↓
Fetch request?
Yes→handleFetch hook runs
↓
Fetch response returned
↓
Route processing
↓
Error occurs?
Yes→handleError hook runs
↓
Error handled or rethrown
↓
Response sent back to client
This flow shows how SvelteKit hooks run in order: handle runs first on every request, handleFetch wraps fetch calls, and handleError runs if an error happens.
Execution Sample
Svelte
export const handle = async ({ event, resolve }) => {
  console.log('handle start');
  const response = await resolve(event);
  console.log('handle end');
  return response;
};
This handle hook logs before and after the request is processed.
Execution Table
StepHookActionOutput/Effect
1handleLogs 'handle start'Console: handle start
2handleCalls resolve(event) to process requestRequest processing continues
3handleFetchIntercepts fetch call inside resolveCan modify request or response
4handleFetchReturns fetch responseResponse passed back to resolve
5handleLogs 'handle end'Console: handle end
6handleReturns responseResponse sent to client
7handleErrorIf error thrown during resolveLogs or modifies error response
8handleErrorReturns error response or rethrowsError response sent or propagated
9-No more hooks, request cycle endsRequest complete
💡 Request cycle ends after response is sent or error handled.
Variable Tracker
VariableStartAfter Step 2After Step 4After Step 6Final
eventRequest infoPassed to resolveSameSameSame
responseundefinedundefinedFetch responseResponse returnedResponse sent
errorundefinedundefinedundefinedSet if errorHandled or rethrown
Key Moments - 3 Insights
Why does handle hook call resolve(event)?
Because resolve(event) continues processing the request and returns the response. Without calling resolve, the request would not proceed (see execution_table step 2).
When does handleFetch run during the request?
handleFetch runs whenever a fetch call happens inside resolve(event), allowing interception of fetch requests (see execution_table steps 3 and 4).
What happens if an error occurs during resolve(event)?
handleError runs to catch and handle the error, allowing logging or custom error responses before sending back to the client (see execution_table steps 7 and 8).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what does the handle hook do at step 5?
AIntercepts fetch request
BCalls resolve(event)
CLogs 'handle end'
DHandles an error
💡 Hint
Check the 'Action' column at step 5 in the execution_table.
At which step does handleFetch return the fetch response?
AStep 2
BStep 4
CStep 6
DStep 7
💡 Hint
Look for 'Returns fetch response' in the 'Action' column.
If no error occurs during resolve, which hook does NOT run?
AhandleError
Bhandle
ChandleFetch
Dresolve
💡 Hint
See execution_table steps 7 and 8 about error handling.
Concept Snapshot
SvelteKit hooks run in this order:
1. handle: runs on every request, calls resolve(event) to continue.
2. handleFetch: wraps fetch calls inside resolve for interception.
3. handleError: runs if an error occurs during resolve.
Use handle to modify requests/responses, handleFetch to modify fetch, handleError to catch errors.
Full Transcript
In SvelteKit, hooks let you run code during the request lifecycle. The handle hook runs first on every request and must call resolve(event) to continue processing. Inside resolve, fetch calls trigger handleFetch, which can modify fetch requests or responses. If an error happens during resolve, handleError runs to catch and handle it. This flow ensures you can customize requests, fetches, and errors in one place.

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

  1. Step 1: Understand the role of handle hook

    The handle hook runs on every request and can modify the request or response.
  2. Step 2: Compare with other hooks

    handleError is for errors, handleFetch is for fetch interception, so they don't manage requests/responses directly.
  3. Final Answer:

    To manage and modify incoming requests and outgoing responses -> Option D
  4. Quick Check:

    handle = manage requests/responses [OK]
Hint: Remember: handle = request/response management [OK]
Common Mistakes:
  • Confusing handle with handleError
  • Thinking handleFetch manages requests directly
  • Assuming handle is for client-side events
2. Which of the following is the correct syntax to define a handleError hook in hooks.server.js?
easy
A. export function handleError({ request, response }) { return response; }
B. export async function handleError(event) { console.error(event.error); }
C. export function handleError({ error, event }) { return { message: error.message }; }
D. export function handleError({ fetch, event }) { return fetch(event); }

Solution

  1. Step 1: Recall handleError parameters

    The handleError hook receives an object with error and event.
  2. Step 2: Check syntax correctness

    export function handleError({ error, event }) { return { message: error.message }; } correctly destructures { error, event } and returns an object with a message.
  3. Final Answer:

    export function handleError({ error, event }) { return { message: error.message }; } -> Option C
  4. Quick Check:

    handleError({ error, event }) correct syntax [OK]
Hint: handleError gets { error, event } object [OK]
Common Mistakes:
  • Using wrong parameters like request or fetch
  • Not destructuring the error object
  • Returning response instead of error info
3. Given this handleFetch hook, what will be logged when the app fetches /api/data?
export async function handleFetch({ request, fetch }) {
  console.log('Fetching:', request.url);
  const response = await fetch(request);
  return response;
}
medium
A. Fetching: http://localhost/api/data
B. Fetching: /api/data
C. Fetching: undefined
D. No output logged

Solution

  1. Step 1: Understand handleFetch parameters

    The request object has a full URL in its url property.
  2. Step 2: Analyze the console.log statement

    The code logs 'Fetching:' plus the full request.url, which includes the origin like 'http://localhost/api/data'.
  3. Final Answer:

    Fetching: http://localhost/api/data -> Option A
  4. Quick Check:

    request.url logs full URL [OK]
Hint: request.url in handleFetch is full URL [OK]
Common Mistakes:
  • Expecting only path instead of full URL
  • Thinking request.url is undefined
  • Assuming no console output
4. Identify the error in this handle hook code snippet:
export async function handle({ event, resolve }) {
  const response = await resolve(event);
  response.headers.set('X-Custom', 'value');
  return response;
}
medium
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

  1. Step 1: Check response header modification

    The response object is immutable; headers cannot be set directly on it.
  2. Step 2: Confirm other parts are correct

    Await is used correctly, parameter names are valid, and handle can be async.
  3. Final Answer:

    Cannot modify headers on the response object directly; it is immutable -> Option A
  4. 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

  1. 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.
  2. 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.
  3. 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.
  4. 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
  5. 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 unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard