Search code examples
rubyexceptionerror-handlingexitbacktrace

Write a simple error message without a backtrace


I want to write to either STDOUT or STDERR a clean, simple error message for the user, without the (verbose) backtrace. I am currently using raise to write the error message and exit, as in this simplified example:

#!/usr/bin/env ruby

def bar
  raise "this needs to be clean, no backtrace"
end

bar

It writes this to STDERR:

/Users/foo/test/test1.rb:4:in `bar': this needs to be clean, no backtrace (RuntimeError)
        from /Users/foo/test/test1.rb:7:in `<main>'

I want to write just this part:

this needs to be clean, no backtrace 

The real-life example has a much more verbose backtrace, and multiple raise statements to handle different failure modes with customized messages.

I am aware that I can do something like this (for clean STDOUT), but I want to avoid repetitive code:

puts "this needs to be clean, no backtrace"
raise "this needs to be clean, no backtrace"

Related:

  • Unhandled Exceptions in Ruby - this answer suggests a more complex way of handling exceptions (namely, catching and printing the error message) than I need. All I need is: (a) raise - or something similar - to terminate the program immediately, and (b) print just the error message, not the full stack trace or backtrace, which is confusing for our users.

Solution

  • If you just want to output to stderr, you could use warn (or write to $stderr directly), maybe along with exit:

    def bar
      warn "this needs to be clean, no backtrace"
      exit(false)
    end
    
    bar
    

    To alter the way global exception handlers work, you could register an at_exit handler which checks for the exception class, prints its message and silences stdout in order to suppress the backtrace. Something like this:

    class SimpleError < StandardError ; end
    
    at_exit do
      if $!.is_a?(SimpleError)
        $stderr.puts($!.message)
        $stderr.reopen(IO::NULL)
      end
    end
    
    def bar
      raise SimpleError, "this needs to be clean, no backtrace"
    end
    
    bar
    

    It would probably be a good idea to make that kind of error handling optional.