Edit

Error handling

This page is about handling: bugs, expected errors, and network errors.

Bugs

If a telefunction has a bug:

// hello.telefunc.js
// Environment: server
 
export { hello }
 
async function hello(name) {
  // Typo => syntax error => it should be `name` instead of `namee`
  return 'Hello ' + namee
}
// hello.telefunc.ts
// Environment: server
 
export { hello }
 
async function hello(name: string) {
  // Typo => syntax error => it should be `name` instead of `namee`
  return 'Hello ' + namee
}

Then a telefunction call throws an error:

<!-- index.html -->
<!-- Environment: client -->
 
<html>
  <body>
    <script type="module">
      import { hello } from './hello.telefunc.js'
 
      try {
        await hello('Eva')
        console.log("I'm never printed")
      } catch(err) {
        console.log(err.message) // Prints 'Internal Server Error'
        // E.g. show a popup "Something went wrong. Try again (later)."
        // ...
      }
    </script>
  </body>
</html>

To avoid leaking sensitive information, Telefunc doesn't send the original Error object to the frontend.

Expected Errors

An error thrown by a telefunction doesn't have to be a bug — it can be expected.

For example:

  • An authentication library throwing an error if the user isn't logged in.
  • A validation library throwing an error upon invalid data.

In this situation, you can:

  1. Propagate the error to the frontend, or
  2. handle the error on the server-side.

1. Propagate the error to the frontend.

You can propagate error information to the frontend like this:

import { validate } from 'some-library'
 
function onFormSubmit(data) {
  try {
    validate(data)
  } catch (err) {
    return {
      errorMessage: `Data is invalid: ${err.message}. Please enter valid data.`
    }
  }
}

You can also use throw Abort(someValue):

import { validate } from 'some-library'
import { Abort } from 'telefunc'
 
function onFormSubmit(data) {
  try {
    validate(data)
  } catch (err) {
    throw Abort({
      errorMessage: `Data is invalid: ${err.message}. Please enter valid data.`
    })
  }
}

In general, we recommend using return { someValue } instead of throw Abort(someValue), see explanation at Guides > Form validation > throw Abort(someValue).

You must catch the error and use throw Abort(someValue) because Telefunc doesn't send the original Error object to the frontend (in order to avoid leaking sensitive information).

See also: Guides > Permissions > getContext() wrapping.


2. Handle the error on the server-side.

Register an onBug() hook — it's called whenever a telefunction throws a bug (any error that isn't Abort()):

// server.js
// Environment: server
 
import { onBug } from 'telefunc'
 
onBug((err) => {
  // Error handling (e.g. report to Sentry, Bugsnag, ...)
})
// server.ts
// Environment: server
 
import { onBug } from 'telefunc'
 
onBug((err) => {
  // Error handling (e.g. report to Sentry, Bugsnag, ...)
})

With the low-level serve(), the error is also exposed at httpResponse.err.

Network Errors

If the user's browser can't connect to your server:

<!-- index.html -->
<!-- Environment: client -->
 
<html>
  <body>
    <script type="module">
      import { hello } from './hello.telefunc.js'
      import { NetworkError } from 'telefunc/client'
 
      try {
        await hello('Eva')
      } catch(err) {
        if (err instanceof NetworkError) {
          // There is a network problem:
          //  - the user isn't connected to the internet, or
          //  - your server is down.
          console.log(err.message) // Prints 'No Server Connection'
        }
      }
    </script>
  </body>
</html>

See also