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.

You can handle the thrown error at your Telefunc server middleware:

// server.js
 
// Server (Express.js/Fastify/...)
 
import { telefunc } from 'telefunc'
 
// Telefunc middleware
app.all('/_telefunc', async (req, res) => {
  const httpResponse = await telefunc(/* ... */)
  // Telefunc exposes any error thrown by a telefunction at httpResponse.err
  if (httpResponse.err) {
    // Error handling
  }
})
// server.ts
 
// Server (Express.js/Fastify/...)
 
import { telefunc } from 'telefunc'
 
// Telefunc middleware
app.all('/_telefunc', async (req: Request, res: Response) => {
  const httpResponse = await telefunc(/* ... */)
  // Telefunc exposes any error thrown by a telefunction at httpResponse.err
  if (httpResponse.err) {
    // Error handling
  }
})

Also see API > getContext() > Provide.

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'
 
      try {
        await hello('Eva')
      } catch(err) {
        if (err.isConnectionError) {
          // 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