-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: differentiate between 404
and 500
when rendering an error page
#10565
Conversation
🦋 Changeset detectedLatest commit: 13aea04 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
404
and 500
when rendering error page404
and 500
when rendering an error page
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mhhm this is a tough one. It feels a bit weird to use the status code for this - could you end up in the root layout with state.error
in other circumstances where you would also want to load a prerendered file? Is something like "try real fetch
first if state.error
and state.depth > 0
(which indicates an internal fetch
request" better?
Replaced the fix with this and I think it works well. |
@@ -457,6 +457,10 @@ export async function respond(request, options, manifest, state) { | |||
return response; | |||
} | |||
|
|||
if (state.error && state.depth > 0) { | |||
return await fetch(request); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could cause an infinite chain of requests.
Eg:
A request comes for kit.svelte.dev/non-existent
, which is a 404 so it tries to render the error page, which makes a request to /nav.json
but maybe that had a typo in the path and then that response also tries to do the same... and so on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gah there's no easy solution, is there? 😓 How could we catch this case of "error from within error state", which should probably reroute to the fallback error.html
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh whoops. For some reason I thought the below would kick in. Would adding something similar solve this issue?
kit/packages/kit/src/runtime/server/page/index.js
Lines 19 to 22 in 8c642cf
/** | |
* The maximum request depth permitted before assuming we're stuck in an infinite loop | |
*/ | |
const MAX_DEPTH = 10; |
kit/packages/kit/src/runtime/server/page/index.js
Lines 34 to 39 in 8c642cf
if (state.depth > MAX_DEPTH) { | |
// infinite request cycle detected | |
return text(`Not found: ${event.url.pathname}`, { | |
status: 404 // TODO in some cases this should be 500. not sure how to differentiate | |
}); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'd kick in if the state was saved, but with the fetch it ends up being a completely new request that the server doesn't know it's related to the previous one in any way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe a custom header to identify the request? Or do we generally avoid adding extra headers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a header to the fetch request so that the server can identify when we're coming from an error state. The error.html
will get returned in this case to prevent the infinite request chain.
@s3812497 a heads up that this fix may not have worked: sveltejs/svelte#9337 (comment) |
I checked the Kit site while reviewing this PR and it worked on that, not sure what's going on with the Svelte site. |
I tested the svelte site locally and it's happening because of an error while rendering the root layout. TypeError: Cannot read properties of null (reading 'startsWith') I think in this case, it's working correctly. Since the error occurred while rendering the default error page, we get the static fallback error page. However, the error message is incorrect. It should be "Internal Error" although the route we are navigating to doesn't exist. kit/packages/kit/src/runtime/server/utils.js Line 107 in fb611ef
|
fixes #10556
Differentiating between
404
and500
when rendering an error page prevents the load fetch from returning an internal error when it should be making a fetch request.This fails because SvelteKit tries to render an error page, fetch the prerendered endpoint, but the fetch returns a 500 when it detects
state.error
istrue
(set to true because we are rendering a 404 error page).I couldn't include a test without it affecting other tests. This is because the reproduction requires adding afetch
to a prerendered endpoint in the root layout (causing other tests to fail).Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
Tests
pnpm test
and lint the project withpnpm lint
andpnpm check
Changesets
pnpm changeset
and following the prompts. Changesets that add features should beminor
and those that fix bugs should bepatch
. Please prefix changeset messages withfeat:
,fix:
, orchore:
.