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.