Improved stacktrace display in Ruby 2.5

Trace

Reading long stacktraces is tedious. Luckily, there is good news. Ruby 2.5 makes them slightly more convenient.

Installing Ruby 2.5

Ruby 2.5 has not been released yet but you can easily install first release candidate. This is how to do it in RVM

$ rvm get head
$ rvm install ruby-2.5.0-preview1

Minimal Example

Consider this convoluted example that raises an error.

class Foo
  def bar
    error
  end

  def error
    raise "oops"
  end
end

class Bar
  def baz
    Foo.new.bar
  end
end

Bar.new.baz

This is what gets printed on Ruby 2.4.

$ rvm use 2.4.2
$ ruby example.rb
 
example.rb:7:in `error': oops (RuntimeError)
from example.rb:3:in `bar'
from example.rb:13:in `baz'
from example.rb:17:in `<main>'

Now, let’s look at Ruby 2.5.

$ rvm use 2.5.0-preview1
$ ruby example.rb
 
Traceback (most recent call last):
3: from example.rb:17:in `<main>'
2: from example.rb:13:in `baz'
1: from example.rb:3:in `bar'
example.rb:7:in `error': oops (RuntimeError)

Did you spot the difference? In Ruby 2.4 the line that caused the error is printed at the top while in Ruby 2.5 it’s at the bottom.

I think this is small but really useful improvement. Especially, when it comes to reading long stacktraces with a load of stack frames from 3rd party libraries. Usually, you have to scroll up to see the line that raises the error. Sure, it takes just a second or two but if repeat it multiple times every day, week and year then the time needed just to scroll up becomes significant. What a waste! With Ruby 2.5 you will see the most interesting bits of the stacktrace without any additional effort.

Gotchas

There are a few non-obvious aspects that are worth mentioning.

Experimental

It’s an experiment feature. It’s possible that the Ruby Core Team will decide to remove it in the final release of Ruby 2.5.

Rails and RSpec

It was surprising to me that stacktraces in Rails behave in the same way in both Ruby 2.4 and 2.5. I expected that with Ruby 2.5 the stacktrace would be reversed but it’s not. After a bit of thinking it made sense. The app server, say Puma or Unicorn, intercepts the exception and prints the stacktrace itself. Whether it runs on Ruby 2.4 or 2.5 doesn’t matter.

The same behaviour can be observed in RSpec.

Redirected STDERR

If stderr is not a TTY then the usual non-reversed stacktrace is printed. Say, you want to pipe the output to another command.

$ ruby example.rb 2>&1 | cat
 
example.rb:7:in `error': oops (RuntimeError)
from example.rb:3:in `bar'
from example.rb:13:in `baz'
from example.rb:17:in `<main>'

Without redirecting the stderr the stacktrace is reversed.

$ ruby example.rb
 
Traceback (most recent call last):
3: from example.rb:17:in `<main>'
2: from example.rb:13:in `baz'
1: from example.rb:3:in `bar'
example.rb:7:in `error': oops (RuntimeError)

Thanks for reading! If you’d like to read more about exciting features in Ruby 2.5 have a look at yield_self.

comments powered by Disqus