🎓 A1Learner
🔍
0 of 54 lessons completed

Elixir Raising and Rescuing

Raising is stopping the current work by throwing an error with a message. Rescuing is catching that error so the program can react and carry on.

A rescued raise prints its message

The raise throws an error before the line after it can run. The rescue branch catches it and prints its message.

try do
  raise "boom"
rescue
  e -> IO.puts(Exception.message(e))
end

The program continues after a rescue

Checker raises for a negative score and returns the score otherwise. The rescue prints the message, and the line after the block still runs.

defmodule Checker do
  def check(score) when score < 0, do: raise("negative score")
  def check(score), do: score
end

try do
  IO.puts(Checker.check(-1))
rescue
  e -> IO.puts("Rescued: #{Exception.message(e)}")
end

IO.puts("Program continues")

Rescue can supply a fallback value

A try block is an expression, so it can return a value. Here the rescue branch builds the fallback text from the message.

result =
  try do
    raise "missing name"
  rescue
    e -> "Fallback for: #{Exception.message(e)}"
  end

IO.puts(result)

Example

defmodule Signup do
  def require_name(name) when name == "", do: raise("name is empty")
  def require_name(name), do: name
end

try do
  IO.puts("Saved: #{Signup.require_name("Ana")}")
rescue
  e -> IO.puts("Cannot save: #{Exception.message(e)}")
end

try do
  IO.puts("Saved: #{Signup.require_name("")}")
rescue
  e -> IO.puts("Cannot save: #{Exception.message(e)}")
end

IO.puts("Done")

Key points

  • RuntimeError: the standard error created by raise, carrying the text given to it.
  • Raise: raise "text" stops the code at that point and throws the error upward.
  • Flow: an error nobody rescues stops the whole script.
  • Try: code inside a try block runs until it finishes or raises an error.
  • Rescue: the rescue branch runs when the try code raises an error.
  • Message: Exception.message(e) returns the text stored in the rescued error.

In this example, the first try block saves Ana because require_name returns the name. The second call raises "name is empty", so its rescue branch prints the cannot-save line. The final line still prints, which shows the program carried on.

Note

rescue suits rare failures, while expected failures often return {:error, reason} tuples instead.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

After raise "boom" is rescued as e, what does Exception.message(e) return?