Raising an Exception

Learn how to handle and implement exceptions in Elixir.

We'll cover the following

Elixir (like Erlang) takes the view that errors should normally be fatal to the processes in which they occur. A typical Elixir application’s design involves many processes, which means the effects of an error will be localized. A supervisor will detect the failing process, and the restart will be handled at that level.

For that reason, we won’t find much exception-handling code in Elixir programs. Exceptions are raised, but we rarely catch them. Use exceptions for things that are exceptional— that is, things that should never happen.

Implementation

We can raise an exception using the raise function. At its simplest, we pass it a string, and it generates an exception of type RuntimeError.

iex> raise "Giving up"
** (RuntimeError) Giving up
    erl_eval.erl:572: :erl_eval.do_apply/6

We can also pass the type of exception, along with other optional fields. All exceptions implement at least the message field.

iex> raise RuntimeError
** (RuntimeError) runtime error
erl_eval.erl:572: :erl_eval.do_apply/6
iex> raise RuntimeError, message: "override message" 
** (RuntimeError) override message
    erl_eval.erl:572: :erl_eval.do_apply/6

We can intercept exceptions using the try function. It takes a block of code to execute and optional rescue, catch, and after clauses.

The rescue and catch clauses look a bit like the body of a case function. They take patterns and code to execute if the pattern matches. The subject of the pattern is the exception that was raised.

Here’s an example of exception handling in action. We define a module that has the public function start. It calls a different helper function depending on the value of its parameter. With 0, it runs smoothly. With 1, 2, or 3, it causes the VM to raise an error, which we catch and report.

Get hands-on with 1400+ tech skills courses.