Error Handling

Result Type

In gleam, when an operation can fail, it generally returns a Result. It can be one of two things:

  1. An Ok wrapping the thing you want.
  2. An Error wrapping the value that represents what went wrong.
type Result(t, e) {
  Ok(t)
  Error(e)
}

By treating errors as regular values, it allows the user to see that a function can fail just by looking at its return type:

fn() -> Result(a, b)

You can then pattern match on the value returned by the function:

case do_work() {
  Ok(value) -> todo as "do something with the value"
  Error(err) -> todo as "handle error"
}

Custom Error Types

You can define your custom error types at top level and return them from functions when necessary.

pub type AuthError {
  /// Password doesnt match
  WrongPassword
  /// User not found in the Databse
  NotFound
  /// User account is inactive
  AccountDisabled
}

pub fn verify_login(
  ctx ctx: Context,
  email email: String,
  password password: String,
) -> Result(uuid.Uuid, AuthError) {
  // Body of the function 
}

The gleam/result module

The result.try function from the standard library takes a Result and a callback function describing what to do with the value in case of success. If the result is an Error, it will simply return it, without calling the callback function.

result.try(do_work(), fn(a) {
  io.println(a)
  Ok(Nil)
})

To avoid callback hell, result.try can be paired with use to keep your nesting minimal. If a function fail at any time during the execution, its error will be returned immediately.

use wibble <- result.try(failing_one())
use wobble <- result.try(failing_two())

do_work(wibble, wobble)