Write a simple error message without a backtrace

278 Views Asked by At

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.
2

There are 2 best solutions below

0
Stefan On BEST ANSWER

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.

2
Arctodus On

Are you trying to rewrite the way Ruby writes uncaught exceptions to STDERR? I dont know if thats easily done (or advisable).

You can override the backtrace in a custom exception though, which wont affect anything else.

class ExceptionWithoutBacktrace < StandardError
  def backtrace
    []
  end
end

raise ExceptionWithoutBacktrace, "This should be printed clean"