Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to catch a server error in sapper (svelte)

I am translating my little website from express+handlebars to an express+sapper project.

I would like to catch server side errors (for instance, a voluntary error when you go to /api/error) and render them using the sapper _error.svelte template.

I tried just throwing the error without my custom handler, but it returns an ugly text page with only the error stack, and does not seem to be catched by sapper's error handler

so I added my own error handler, and I can render HTML (bare, with no css yet) but is there a way I could use the sapper _error.svelte template ?

// ----------------------- src/server.js
import sirv from 'sirv'
import express from 'express'
import compression from 'compression'
import * as sapper from '@sapper/server'

import fatal500 from './middlewares/fatal500'

const { PORT, NODE_ENV } = process.env
const dev = NODE_ENV === 'development'

const app = express()

app.use(compression({ threshold: 0 }))
app.use(sirv('static', { dev }))

// the voluntary error thrower --------------------------------
app.get('/api/error', (req, res, next) => {
  const error = new Error('this is a voluntary error')
  error.code = 'VOLUNTARY'
  next(error)
})

app.use(sapper.middleware())

app.use(fatal500) // the custom error handler -----------

app.listen(PORT, err => {
  if (err) console.log('error', err)
})

// ---------------------src/middlewares/fatal500.js

export default function fatal500 (err, req, res, next) {
  if (err.code !== 'VOLUNTARY') console.error(err.stack)

  try {
    res.status(500)
      .type('html')
      .send(
        '<h1>Oooops ... 500 server error</h1>' +
        '<p>It seems the server has encountered an error,<br/>' +
        '   try to <a href=\'/\'> return to the website</a><br/>' +
        '   or to <a href="mailto:[email protected]">send me the stack</a>' +
        '</p>' +
        '<h2>Error Stack :</h2>' +
        '<pre class="code"><code>' +
        err.stack +
        '</code></pre>'
      )
  } catch (e) {
    res.status(500)
      .type('text')
      .send(
        '\n\n' +
        '**************************************\n' +
        'Ooops ... 500\n' +
        'the server encountered an unhandled error,\n\n' +
        'if it is not voluntary (going to /api/error)\n' +
        'please EMAIL ME THE FOLLOWING STACK at\n' +
        '[email protected]\n' +
          '**************************************\n\n' +
        'ORIGINAL ERROR STACK ------------------\n\n' +
        err.stack + '\n\n' +
        'ERROR HANDLING STACK ------------------\n\n' +
        e.stack
      )
  }
}
like image 804
gui3 Avatar asked Feb 21 '20 15:02

gui3


1 Answers

Javascript is notoriously difficult to catch all types of error in. Sapper doesn't have any explicit handling for these errors either, however there is a neat third party component which allows this.

The first way, which I personally use, is this library: https://www.npmjs.com/package/@crownframework/svelte-error-boundary

Which essentially will catch errors (within reason) at the boundary of a component. It provides a way to attach a function so that you can then do what you like with that error.

I'm currently in the process of building this into Svelte itself. You can feed back on the RFC https://github.com/sveltejs/rfcs/blob/rfc/error-boundary/text/0000-error-boundary.md

The way in which I use the boundary is that I attach the handler to sentry - https://sentry.io which will break down and diagnose issues for you, so that you can fix them. Take a look!

like image 155
Antony Jones Avatar answered Nov 11 '22 10:11

Antony Jones