sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.47k stars 1.89k forks source link

Redirects to error pages occur when an expected error is thrown #5988

Closed theetrain closed 2 years ago

theetrain commented 2 years ago

Describe the bug

Utilizing the error helper documented here: https://kit.svelte.dev/docs/load#errors When I use throw error(400) in a server file, its respective page redirects to an error page instead of passing the response successfully.

I expect to be able to handle the response in my +page.svelte file, but I cannot. It could be my misunderstanding of the docs, or unintended behaviour of throw error().

Reproduction

Reproduction demo: https://stackblitz.com/edit/sveltekit-load-errors?file=src%2Froutes%2F%2Bpage.server.js,src%2Froutes%2F%2Bpage.svelte&terminal=dev

Utilizing error like so:

+page.server.js

import { error } from '@sveltejs/kit';

export function load() {
  throw error(400, 'missing something');

  return;
}

+page.svelte

<script>
// export let data
import { onMount } from 'svelte'

export let data

let response
onMount(async ()=>{
  try {
    response = await fetch('/')
  } catch (error) {
    console.log('some error')
  }
})
</script>

<p>Returned response is: {JSON.stringify(data)}</p>

<p>Fetched response is: {JSON.stringify(response)}</p>
  1. Run project and navigate to the root page
  2. Observe error page being shown instead of the contents of +page.svelte

Logs

No response

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (4) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.14.2 - /usr/local/bin/node
    Yarn: 1.22.10 - /bin/yarn
    npm: 7.17.0 - /bin/npm
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.64 
    @sveltejs/kit: next => 1.0.0-next.416 
    svelte: ^3.46.0 => 3.49.0 
    vite: ^3.0.0 => 3.0.8

Severity

blocking an upgrade

Additional Information

No response

Conduitry commented 2 years ago

This is the intended behavior. If you throw an error from a load function, an error page gets displayed. You aren't returning any data to pass into the corresponding +page.svelte. If you want to display that page but in some sort of error state, that needs to be part of the data returned by load and needs to be handled accordingly in +page.svelte.

theetrain commented 2 years ago

@Conduitry thanks for your reply!

I suppose I misinterpreted this line from the docs:

For expected errors, use the error helper from @sveltejs/kit to specify the HTTP status code and an optional message. ...If an unexpected error is thrown, SvelteKit will invoke handleError and treat it as a 500 Internal Server Error. -- https://kit.svelte.dev/docs/load#errors

From what I've now learned:

If the above is correct, perhaps I can contribute to the docs with this change to add clarity:

If an error is thrown during load, the nearest [+error.svelte](https://kit.svelte.dev/docs/routing#error) 
will be rendered. For expected errors, use the error helper from @sveltejs/kit to specify the HTTP 
status code and an optional message:

[[example]]

+If you want your page to handle errors manually, do not throw an error and 
+include an appropriate status code and message as part of your response:

+/** @type {import('./$types').LayoutServerLoad} */
+export function load({ locals }) {
+  if (!locals.user) {
+    return {
+      status: 401,
+      title: 'User not logged in'
+    }
+  }
+
+  return
+}

If an unexpected error is thrown, SvelteKit will invoke [handleError](https://kit.svelte.dev/docs/hooks#handleerror)
and treat it as a 500 Internal Server Error.

My only remaining concern with current behaviour is it's up to the developer to form a proper RFC 7807 Problem Details response that could get boiler-platey. Is there interest in having the error helper return a response that does not lead to the +error.svelte page? I noticed it's currently possible to do this:

import { error } from '@sveltejs/kit';

export function load() {
  return {
    ...error(400, 'missing something')
  };
}

(somewhat inspired by: https://github.com/ahmadnassri/node-api-problem)

Though this doesn't include the application/problem+json media type. Please let me know if there's interest in something like this.