How do I get ruby to print a full backtrace instead of a truncated one?

Viewed 172691

When I get exceptions, it is often from deep within the call stack. When this happens, more often than not, the actual offending line of code is hidden from me:

tmp.rb:7:in `t': undefined method `bar' for nil:NilClass (NoMethodError)
        from tmp.rb:10:in `s'
        from tmp.rb:13:in `r'
        from tmp.rb:16:in `q'
        from tmp.rb:19:in `p'
        from tmp.rb:22:in `o'
        from tmp.rb:25:in `n'
        from tmp.rb:28:in `m'
        from tmp.rb:31:in `l'
         ... 8 levels...
        from tmp.rb:58:in `c'
        from tmp.rb:61:in `b'
        from tmp.rb:64:in `a'
        from tmp.rb:67

That "... 8 levels..." truncation is causing me a great deal of trouble. I'm not having much success googling for this one: How do I tell ruby that I want dumps to include the full stack?

10 Answers

Exception#backtrace has the entire stack in it:

def do_division_by_zero; 5 / 0; end
begin
  do_division_by_zero
rescue => exception
  puts exception.backtrace
  raise # always reraise
end

(Inspired by Peter Cooper's Ruby Inside blog)

This produces the error description and nice clean, indented stacktrace:

begin               
 # Some exception throwing code
rescue => e
  puts "Error during processing: #{$!}"
  puts "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
end

IRB has a setting for this awful "feature", which you can customize.

Create a file called ~/.irbrc that includes the following line:

IRB.conf[:BACK_TRACE_LIMIT] = 100

This will allow you to see 100 stack frames in irb, at least. I haven't been able to find an equivalent setting for the non-interactive runtime.

Detailed information about IRB customization can be found in the Pickaxe book.

Almost everybody answered this. My version of printing any rails exception into logs would be:

begin
    some_statement
rescue => e
    puts "Exception Occurred #{e}. Message: #{e.message}. Backtrace:  \n #{e.backtrace.join("\n")}"
    Rails.logger.error "Exception Occurred #{e}. Message: #{e.message}. Backtrace:  \n #{e.backtrace.join("\n")}"
end

You can also use backtrace Ruby gem (I'm the author):

require 'backtrace'
begin
  # do something dangerous
rescue StandardError => e
  puts Backtrace.new(e)
end
Related