Defining Your Own Exceptions

Exceptions in Elixir are basically records. You can define your own exceptions by creating a module. Inside it, use defexception to define the various fields in the exception, along with their default values. Because you’re creating a module, you can also add functions—often these are used to format the exception’s fields into meaningful messages.

Say we’re writing a library to talk to a Microsoft Kinect controller. It might want to raise an exception on various kinds of communication errors. Some of these are permanent, but others are likely to be transient and can be retried. We’ll define our exception with its (required) message field and an additional can_retry field. We’ll also add a function that formats these two fields into a nice message.

exceptions/defexception.ex
 defmodule​ KinectProtocolError ​do
 
 defexception​ ​message:​ ​"​​Kinect protocol error"​,
 can_retry:​ false
 
 def​ full_message(me) ​do
 "​​Kinect failed: ​​#{​me.message​}​​, retriable: ​​#{​me.can_retry​}​​"
 end
 
 end

Users of our library could write code like this:

exceptions/defexception.ex
 try​ ​do
  talk_to_kinect()
 rescue
  error ​in​ [KinectProtocolError] ->
  IO.puts KinectProtocolError.full_message(error)
 if​ error.can_retry, ​do​: schedule_retry()
 end

If an exception gets raised, the code handles it and possibly retries:

 Kinect failed: usb unplugged, retriable: true
 Retrying in 10 seconds