kit
kit copied to clipboard
500 responses from @sveltejs/kit/src/routing/client.js are ambiguous and cannot be distinguished from server responses
Describe the bug
@sveltejs/kit/src/routing/client.js returns 500 response when certain events happen (too many redirects, failed/timed out fetch, etc.).
https://github.com/sveltejs/kit/blob/a2b9c3ecd2a41fae41a42141d87dc8fec43b8830/packages/kit/src/runtime/client/client.js#L291 https://github.com/sveltejs/kit/blob/a2b9c3ecd2a41fae41a42141d87dc8fec43b8830/packages/kit/src/runtime/client/client.js#L815 https://github.com/sveltejs/kit/blob/a2b9c3ecd2a41fae41a42141d87dc8fec43b8830/packages/kit/src/runtime/client/client.js#L892 https://github.com/sveltejs/kit/blob/a2b9c3ecd2a41fae41a42141d87dc8fec43b8830/packages/kit/src/runtime/client/client.js#L1390 https://github.com/sveltejs/kit/blob/a2b9c3ecd2a41fae41a42141d87dc8fec43b8830/packages/kit/src/runtime/client/client.js#L1718
What is the problem? The 500 code response is supposed to be returned by the server only per HTTP spec "The server has encountered a situation it does not know how to handle." And SvelteKit's server does return 500 for all internal issues. When server cannot be reached, returning "500" from the client-side code is incorrect as it is ambiguous and hides the details that are useful.
In a PWA, when e.g. offline, +error.svelte page cannot distinguish if it was a true server-side error, or if there is no connection to the server for some function that absolutely needs it. In the "no connection" case it would be very useful to be able to show informative message "Cannot perform requested operation when offline. Please connect to the Internet" and possibly "Retry" button and maybe "WiFi Settings" button for mobile devices.
Another problem is lack of detail - 500 covers all bad outcomes on the client side and on the server side. It would be nice to have separate codes for each of the conditions on the client side, so the custom error is only shown for the precise problem.
What codes to show instead? Any but not 1xx, 2xx, 3xx, 4xx, 5xx that are defined in HTTP spec. HTTP spec does not have status codes for the client-side, it defines conditions only for the server side (4xx codes are called "Client error responses", but in fact all of them are supposed to be returned by the server).
I propose to assign 6xx codes and call them "client fetch" errors. Can be assigned like: 600 - client-side catch-all "The client has encountered a situation it does not know how to handle and has no idea how describe it in English so a 6xx code can be created." 601 - too many redirects 602 - timeout getting server response 603 - error in branch load (can someone propose a better name?) 604 - error when loading error page 605 - error when loading root error page ... other codes if needed.
If that 6xx codes proposal is not workable (e.g. for "breaking change" in release candidate), then add a "client" field (or something similar) with a unique dis-ambiguation code (though I feel this solution is less logical).
Reproduction
I don't feel the repro is needed here.
Logs
No response
System Info
@sveltejs/kit@next
Severity
blocking all usage of SvelteKit
Additional Information
Can't make informative "connect to Internet" pages for "offline PWA" mode.
This isn't a bug; it's a feature request.
If we did want to expose this sort of information, it definitely shouldn't be via additional custom opaque 6xx error codes - they'd be additional flags exposed somewhere. Not just because it'd be a breaking change, but because there's no reason to make people remember additional fake status codes that we completely made up.
I'm still not sure why your app would need to know with such detail which of these various situations you're in.
You should still be able to use navigator.onLine to check whether the browser thinks it's online, even if this information isn't expose through $page.
This isn't a bug; it's a feature request.
I pondered on it, and decided it's a bug because current code is using status codes incorrectly, violating HTTP spec.
I'm still not sure why your app would need to know with such detail which of these various situations you're in.
I have PWA app that for most parts works offline. But some parts require to be connected. When user navigates to such a place, +error.svelte page kicks in. It can get $page and looking at it, it cannot determine if it should advise the user to connect to the Internet, or the Server is broken with 500.
Going to navigator.onLine is good workaround advice, but if for some reason SK's client cannot reach the server, but navigator is connected, it still will translate "500 Server is broken". UX is bad in this case and cannot be improved. 602 or client: 'timeout' will be deterministic.
but because there's no reason to make people remember additional fake status codes that we completely made up
Making people remember "500 code can be thrown by client for 6 different reasons" is worse than fake 6xx codes. Google will find HTTP 602 in SvelteKit docs.
I argue that all except "too many redirects" are correctly labeled as 500 because these errors ultimately come from a bad server response. Also, all these errors can happen the same during server side rendering on the server, so the isomorphic nature of SvelteKit should try to align behavior here instead of differentiating it. Lastly, you have handleError on the client from which you can probably infer some of these error sources.
@dummdidumm
I argue that all except "too many redirects" are correctly labeled as 500 because these errors ultimately come from a bad server response
Are you saying that catch() on await load_data(url... is from a server sending a response? I don't think so. If there's any response, there's no catch(). Entering the catch() is for either "server down" or "no internet". In either case, it is not server sending a 500 response.
so the isomorphic nature of SvelteKit should try to align behavior here instead of differentiating it.
It should, where it makes sense. But when client can't reach the server, there is no similar error that server produces, because server is only concerned with what it sees. No connection to client is not any server's concern. But it is a concern for the client. So there should be some additional error signaling.