Errors
So far we’ve been assuming that everything works correctly. Sometimes it doesn’t — see what happens when you go to a broken URL, for example.
We can control what is displayed when an error occurs by creating a src/routes/+error.svelte file:
<script lang="ts">
let { error } = $props();
</script>
<main>
<h1>oops!</h1>
<p>{error.message}</p>
</main>
<style>
main {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 1rem;
}
</style> We can also control what message appears from the server:
export const getFile = query(v.string(), async (id) => {
const [d] = await db.select().from(file).where(eq(file.id, id)).limit(1);
if (!d) {
+ error(404, 'File does not exist');
}
if (d.shared || (await requireUser()).id === d.user_id) {
return d;
}
+ error(403, "You don't have permission to view this file. Ask the owner to share it");
}); These are expected errors — a condition wasn’t met, so we gave the user relevant feedback. Sometimes errors are unexpected — something happening in a service you don’t control, or in some cases just a bug.
If we simulate that by throwing a regular error in the getFile query…
throw new Error('oh no!'); …then you’ll notice two things. Firstly, the error was logged, because it’s something you need to investigate. Secondly, the actual message is redacted in favour of ‘Internal Error’, because errors can potentially contain sensitive information.
If you need more control over error handling, you can implement the handleError hook. The quickest way to show that is to hop over to the tutorial.
Don’t forget to delete your ‘oh no!’ error before moving on to the next exercise.