Handling errors

How to:

In Elixir, we often use pattern matching and the case statement to handle different outcomes, including errors.

defmodule Example do
  def divide(a, b) do
    case b do
      0 -> {:error, "Cannot divide by zero."}
      _ -> {:ok, a / b}

# Successful division
{:ok, result} = Example.divide(10, 2)
IO.puts("10 / 2 is #{result}")

# Attempt to divide by zero
{:error, reason} = Example.divide(10, 0)
IO.puts("Error: #{reason}")

Sample output:

10 / 2 is 5.0
Error: Cannot divide by zero.

When you run this Elixir code, you’ll either get a successful division or an error message, depending on your input. No crashes here!

Deep Dive

Way back, error handling was often about checking return values. With Elixir’s functional roots though, we’ve got pattern matching and tagged tuples, like {:ok, value} or {:error, reason}, which are more elegant.

There are other ways to handle errors in Elixir:

  • Elixir’s try and rescue which resemble the traditional try-catch in imperative languages but are used less frequently due to Elixir’s preference for explicitness.
  • Supervisors and GenServers, part of Elixir’s OTP framework, which are more about fault tolerance. They watch your code’s process, ready to restart it if things go awry.

Implementation-wise, Elixir builds on Erlang’s robustness. It treats errors as just another type of message to be handled with all the pattern matching and functional goodness.

See Also

For further reading on error handling in Elixir, check out: