-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Navigation HTTP error handling #12399
Comments
Would <script>
import { preload, goto } from '$app/navigation';
let value = '';
async function customGoto(href) {
try {
await preload(href);
} catch (error) {
alert(error.message)
}
await goto(href);
}
</script>
<input type="text" placeholder="Game ID..." bind:value/>
<button type="button" on:click={async () => await customGoto(`/game/${value}/`} disabled={!value}>Join game</button> |
Sorry for getting back to you late! I found some time to play around and can confirm there's no obvious way to detect errors because it's been explicitly excluded from the preloadData function return. kit/packages/kit/src/runtime/client/client.js Lines 1797 to 1807 in c9b2e65
Here's a "workaround" in the meantime: you can check the data property of the returned result and if there are no keys, then it's probably an error (or the load function just doesn't return data on success). import { preloadData, goto } from '$app/navigation';
async function attemptGoto (pathname) {
const result = await preloadData(pathname);
// load function threw an error
if (result.type === 'loaded' && Object.keys(result.data).length === 0) {
alert('there was an error so we do not navigate');
return;
}
// load function threw a redirect
if (result.type === 'redirect') {
await goto(result.location);
return;
}
// load function was successful
await goto(pathname);
} |
@Rich-Harris should |
That's an interesting workaround. It doesn't work if the target route uses a layout which returns data but, to get around that, I can pass the number of keys (hard-coded) in the layout of the target route to |
It does feel like |
This is a very simple reproduction: https://stackblitz.com/edit/sveltejs-kit-template-default-7retxz?file=src%2Froutes%2F%2Bpage.svelte |
Unfortunately, @eltigerchino's workaround doesn't quite work, since preloadData still returns the layout data even if it couldn't load the page data. I've encountered this issue using |
I've drafted a PR for this fix. I think we can agree it's not a breaking change since it never worked correctly in the first place (status always returned 200 even on errors). The new return type should look something like below: export function preloadData(href: string): Promise<{
type: 'loaded';
status: number;
data: Record<string, any>;
} | {
type: 'redirect';
location: string;
} | {
type: 'error';
status: number;
error: App.Error;
}>; Any thoughts on this? |
Awesome! This was an existing issue so it might be worth creating a separate issue/PR for this, but you showing the type has made me notice that the status is missing is there's a redirect, which seems a bit pointless. For one, if the status is always provided then it makes any logic dependent on the status a lot simpler since it doesn't need to check the type first. But also, there are many redirect HTTP status codes (300 - 399) which could be used by developers to quickly indicate information which the client might want to know before checking the location. |
Currently, the server doesn't return the status property in the __data.json payload if it's a redirect, so we would need to change that if we decide to standardise this. |
Hm, that's a bit annoying, but would I be correct in saying that wouldn't be a breaking change since it would just mean adding (not removing/changing) a property? Or is the keyset used for validation or something? |
It shouldn't be. I haven't heard any objections around returning the status for redirects yet so I tried adding it. The new interface looks something like this: (
| {
type: 'loaded';
data: Record<string, any>;
}
| {
type: 'redirect';
location: string;
}
| {
type: 'error';
error: App.Error;
}
) & {
status: number;
} |
Describe the problem
I have a "form" like this:
Currently, if some error occurs while trying to join the game (e.g: if the game doesn't exist), the error will be shown by the
/game/[gameId]/
route, meaning the user needs to navigate back. Ideally, the error message would be displayed as part of the form.Describe the proposed solution
I'm not sure exactly how the flow from beforeNavigate to onNavigate to afterNavigate works, but I assume SvelteKit would be aware of errors during
onNavigate
in which case$page.error
should be set before theonNavigate
callback is called and thenonNavigate
should have acancel
method similarly tobeforeNavigate
. Alternatively, there could be a dedicatedonNavigationError
Alternatives considered
Have a route which checks if a game exists, then call that before calling
goto
. However, this means I need to check if the game exists twice, which isn't ideal.Importance
would make my life easier
Additional Information
No response
The text was updated successfully, but these errors were encountered: