Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/seven-mangos-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': minor
---

Allow Custom HTTP Status Codes
2 changes: 1 addition & 1 deletion documentation/docs/30-advanced/20-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ If an [unexpected error](errors#Unexpected-errors) is thrown during loading, ren
- you can log the error
- you can generate a custom representation of the error that is safe to show to users, omitting sensitive details like messages and stack traces. The returned value, which defaults to `{ message }`, becomes the value of `$page.error`.

For errors thrown from your code (or library code called by your code) the status will be 500 and the message will be "Internal Error". While `error.message` may contain sensitive information that should not be exposed to users, `message` is safe (albeit meaningless to the average user).
For errors thrown from your code (or library code called by your code) the status will be 500 unless overriden `error.status` and the message will be "Internal Error". While `error.message` may contain sensitive information that should not be exposed to users, `message` is safe (albeit meaningless to the average user).

To add more information to the `$page.error` object in a type-safe way, you can customize the expected shape by declaring an `App.Error` interface (which must include `message: string`, to guarantee sensible fallback behavior). This allows you to — for example — append a tracking ID for users to quote in correspondence with your technical support staff:

Expand Down
10 changes: 9 additions & 1 deletion packages/kit/src/utils/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,17 @@ export function normalize_error(error) {

/**
* @param {unknown} error
* @returns {number}
*/
export function get_status(error) {
return error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500;
if (error instanceof HttpError || error instanceof SvelteKitError) {
return error.status;
}
// For overrides / custom error objects
if (typeof error === 'object' && error !== null && 'status' in error) {
return /** @type {{ status?: number }} */ (error).status ?? 500;
}
return 500;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CustomError extends Error {
constructor(message, errorOpts) {
super(message, errorOpts);
this.status = 422;
}
}

export function GET() {
throw new CustomError('Custom error');
}
6 changes: 6 additions & 0 deletions packages/kit/test/apps/basics/test/server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,12 @@ test.describe('Errors', () => {
expect(await response.text()).toMatch('thisvariableisnotdefined is not defined');
});

test('custom error object', async ({ request }) => {
const response = await request.get('/errors/custom-error');
console.log(response.status());
expect(response.status()).toBe(422);
});

test('returns 400 when accessing a malformed URI', async ({ page }) => {
const response = await page.goto('/%c0%ae%c0%ae/etc/passwd');
if (process.env.DEV) {
Expand Down
Loading