# Raising a new exception in rescue also outputs the original traceback

**URL:** <https://www.ruby-forum.com/t/raising-a-new-exception-in-rescue-also-outputs-the-original-traceback/260344>\
**Category:** Uncategorized\
**Created:** [October 9, 2020, 2:05pm UTC](https://www.ruby-forum.com/t/raising-a-new-exception-in-rescue-also-outputs-the-original-traceback/260344 "2020-10-09T14:05:19Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Wonderer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/e99b99/32.png) [@Wonderer](https://www.ruby-forum.com/u/Wonderer)\
**Post date:** [October 9, 2020, 2:05pm UTC](https://www.ruby-forum.com/t/raising-a-new-exception-in-rescue-also-outputs-the-original-traceback/260344/1 "2020-10-09T14:05:20Z")

</div>

### Description

If a new exception is created and raised from within a rescue block then the traceback begins with lines from the old exception that was being rescued. What I expected and wanted was just the traceback for the new exception showing where it had been raised.

In the example below I wanted the traceback to just show where `Net::HTTP.start` had been called from, and not all the calls within `net/http` that were part of the old exception caught by the `rescue`. The reason for raising a new exception was to hide all the traceback from inside `net/http`, which obscures where it was called from.

The lines from the old traceback appear even though `$@` and the the old exception’s backtrace have both been set to `[]`. Why is this and how can it be prevented? Is the old backtrace held in another global variable that can be cleared before creating and raising the new exception?

This is using ruby 2.6.6 in Windows 10 x64

### Example

#### Code

```auto
require 'net/http'
include Net

uri = URI('http://wrong.host/xxx')

begin
  http = Net::HTTP.start(uri.host, uri.port)
  p http
rescue StandardError => old_e
  old_e.set_backtrace([])
  $@ = []
  new_e = StandardError.new('My message')
  new_e.set_backtrace(caller)
  puts "new exception = #{new_e.inspect}"
  puts "new backtrace = <#{new_e.backtrace.to_a.join("\n")}>"
  puts "new bt_locns = <#{new_e.backtrace_locations.to_a.join("\n")}>"
  puts "new \$@ = <#{$@.to_a.join("\n")}>"
  raise new_e
end

```

#### Output

```auto
D:\Docs\Dev\Ruby\Tests>test_exceptions_1.rb
new exception = #<StandardError: My message>
new backtrace = <D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb:8:in `<main>'>
new bt_locns = <>
new $@ = <>
Traceback (most recent call last):
        9: from D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb:9:in `<main>'
        8: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:605:in `start'
        7: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:925:in `start'
        6: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:930:in `do_start'
        5: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:945:in `connect'
        4: from C:/Ruby26-x64/lib/ruby/2.6.0/timeout.rb:103:in `timeout'
        3: from C:/Ruby26-x64/lib/ruby/2.6.0/timeout.rb:93:in `block in timeout'
        2: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:947:in `block in connect'
        1: from C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:947:in `open'
C:/Ruby26-x64/lib/ruby/2.6.0/net/http.rb:947:in `initialize': getaddrinfo: No such host is known. (SocketError)
D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb: Failed to open TCP connection to wrong.host:80 (getaddrinfo: No such host is known. ) (SocketError)
D:/Docs/Dev/Ruby/Tests/test_exceptions_1.rb:8:in `<main>': My message (StandardError)

```

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [October 9, 2020, 6:17pm UTC](https://www.ruby-forum.com/t/raising-a-new-exception-in-rescue-also-outputs-the-original-traceback/260344/2 "2020-10-09T18:17:47Z")

</div>

There’s also a ‘cause’ field on exceptions - [class Exception - RDoc Documentation](https://docs.ruby-lang.org/en/2.7.0/Exception.html#method-i-cause)  
This is set to $! (the current exception) when a new exception is raised.  
In your case, $! is old\_e, and is getting added to new\_e when raised.

You can use `raise new_e, cause: nil` to avoid this.

Here’s a minimal example:

```auto
begin

begin
  raise StandardError.new 'begin-exception'
rescue StandardError => old_e
  new_e = Exception.new('My message')
  puts "Cause #{new_e.cause}" # there is nothing in 'cause'
  raise new_e # this adds $!, i.e. old_e, as 'cause'
end

rescue Exception => new_e
  puts "Cause #{new_e.cause}" # which we can see printed here
end

```

```auto
$ ruby test.rb 
Cause 
Cause begin-exception

```

If you replace the raise with `raise new_e, cause: nil` you get:

```auto
$ ruby test.rb
Cause
Cause

```

---

<div class="post-metadata">

**Author:** ![Wonderer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/e99b99/32.png) [@Wonderer](https://www.ruby-forum.com/u/Wonderer)\
**Post date:** [October 9, 2020, 7:17pm UTC](https://www.ruby-forum.com/t/raising-a-new-exception-in-rescue-also-outputs-the-original-traceback/260344/3 "2020-10-09T19:17:34Z")

</div>

Thanks @pcl, I can confirm it works in my example.

I had noticed Exception’s `#cause`, but hadn’t realised that it gets set by `raise`.
