NestedExceptions

This simple library adds support for nested exceptions in Ruby.

Why?

It can be really painful to debug a situation where a library rescues an exception and throws a different one, or when it has a bug in its exception handling logic. This gem goes a diving catch and recovers the play!

The best way to learn more about this topic is to investigate the great source of information at the Exceptional Ruby site.

How do I use it?

The best way to use it is to simply add the following line of code to your project:

require 'nested_exceptions/global'

That includes the NestedExceptions module in all of Ruby's base exception classes (except the Exception root class), magically enabling you to debug the trickiest, buggiest libraries.

I'm not sure I want to include it globally

If you want to try it out without extending Ruby's exception classes, you can also do the following:

require 'nested_exceptions'

class MyException < StandardError include NestedExceptions end

That will only extend your class and leave the rest of the exception classes untouched.

Does it change anything?

Yes. A bit of extra information is added to your backtraces. In addition to the standard backtrace, you'll get a little bit of nesting information.

ruby examples/example.rb original

examples/example.rb:32:in `rescue in double_bug': oops (RuntimeError)
  from examples/example.rb:30:in `double_bug'
  from examples/example.rb:42:in `<main>'

ruby examples/example.rb nested

examples/example.rb:30:in `rescue in double_bug': oops (RuntimeError)
  from --- cause: ErrorSpec::InternalError: problem
  from examples/example.rb:20:in `rescue in problem'
  from --- cause: RuntimeError: bug
  from examples/example.rb:10:in `bug'
  from examples/example.rb:14:in `nested_bug'
  from examples/example.rb:18:in `problem'
  from examples/example.rb:24:in `nested_problem'
  from examples/example.rb:28:in `double_bug'
  from examples/example.rb:35:in `<main>'

It also adds two methods to the exception:

  • #root_cause: allows you to easily get the first exception
  • #cause: get the exception (if any) that may have caused this one

Gotchas

Do not include the NestedExceptions module in a subclass before adding it to its superclass. That will cause the nested exceptions feature to deactivate itself to prevent a stack overflow.