Preserving backtrace during exceptions wrapping in Ruby

In this example raising a CustomError hides the original error backtrace.

CustomError = Class.new(StandardError)

def raise_error
  raise StandardError, "Original error" # line 4
end

def call_the_error_raiser
  raise_error # line 8
rescue => e
  raise CustomError, "Error message"
end

begin
  call_the_error_raiser # line 14
rescue StandardError => e
  puts e.inspect
  puts e.backtrace.join("\n")
end

Output (the cause of the original error is lost):

#<CustomError: Error message>
preserve_error_backtrace.rb:10:in `rescue in call_the_error_raiser'
preserve_error_backtrace.rb:7:in `call_the_error_raiser'
preserve_error_backtrace.rb:14:in `<main>'

You can still access the "Original error" backtrace via Exception#cause, but it may be better to preserve the original while raising the custom error, instead of generating a new non-helpful backtrace:

raise CustomError, "Error message", e.backtrace

Output (the cause of the original error is on the first line):

#<CustomError: Error message>
preserve_error_backtrace.rb:4:in `raise_error' ← The cause of the error
preserve_error_backtrace.rb:8:in `call_the_error_raiser'
preserve_error_backtrace.rb:14:in `<main>'

References:



Somewhat related: