If ERB.new(...).result raises an exception how do I get the code and backtrace near it?
Like rails does with it's templates.
I tried what #Nathan suggested before:
begin
ERB.new('<%= fail %>').result
rescue Exception => e
p e
end
=> RuntimeError
That doesn't tell me the position of the error
Try:
begin
ERB.new(...).result
rescue Exception => e
# puts e
# or
# binding.pry if you use the pry gem
end
Related
I have a rake task that loops through rows in CSV file, and inside that loop, there's a begin/rescue block to catch any possible raised exception. But when I run it, it keeps on saying 'rake aborted!' and it is not entering the rescue block
CSV.foreach(path, :headers => true) do |row|
id = row.to_hash['id'].to_i
if id.present?
begin
# call to mymethod
rescue => ex
puts "#{ex} error executing task"
end
end
end
...
def mymethod(...)
...
begin
response = RestClient.post(...)
rescue => ex
raise Exception.new('...')
end
end
Expected: It should finish looping all the rows of the CSV
Actual result: It stops after reaching the 'raise' exception saying that:
rake aborted!
Exception: error message here
...
Caused by:
RestClient::InternalServerError: 500 Internal Server Error
You can use next to skip the faulty step of loop:
CSV.foreach(path, :headers => true) do |row|
id = row.to_hash['id'].to_i
if id.present?
begin
method_which_doing_the_staff
rescue SomethingException
next
end
end
end
And raise the exception inside your method:
def method_which_doing_the_staff
stuff
...
raise SomethingException.new('hasd')
end
I solved this issue by just commenting out the line that is raising an exception because it seems like it the quickest fix for now.
# raise Exception.new('...')
I'm still open to other suggestions if there are any better ways to do it.
Sometimes I need to debug some nasty exception that has its backtrace hidden or truncated, like an ArgumentError without any stack trace.
I am used to debugging with byebug. The problem is that the byebug interpreter is a REPL, so it's not possible to write multiline code. I am trying to figure out how to make an inline rescue and print the backtrace from there, ie I want an inline, REPL compatible, version of
begin
....
rescue => e
puts e.backtrace.join("\n")
end
I have tried
begin; my_crashing_method.call; rescue Exception => e; puts e.backtrace; end
But that line raises a SyntaxError
*** SyntaxError Exception: (byebug):1: syntax error, unexpected keyword_rescue
rescue Exception => e
^
I'm not sure what I am missing ?
EDIT
The line above works fine on a regular IRB/Rails shell but not from a byebug shell
IRB
begin my_crashing_method.call; rescue Exception => e; puts e.backtrace end
Stack Trace shows successfully
Byebug
(byebug) begin; my_crashing_method.call; rescue Exception => e; puts e.backtrace
*** SyntaxError Exception: (byebug):1: syntax error, unexpected end-of-input
begin
^
nil
*** NameError Exception: undefined local variable or method `my_crashing_method' for #<StaticPagesController:0x007fae79f61088>
nil
*** SyntaxError Exception: (byebug):1: syntax error, unexpected keyword_rescue
rescue Exception => e
^
nil
*** NameError Exception: undefined local variable or method `e' for #<StaticPagesController:0x007fae79f61088>
nil
When you enter multiple lines ruby code or in a single line on byebug, you need to escape the semicolon using backlash. The following should do the trick.
begin\; my_crashing_method.call\; rescue Exception => e\; puts e.backtrace end
https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md#command-syntax
I'm trying to figure out the best way to catch a specific error thrown AND the error's message in Ruby on Rails. My use case is that I encounter a timeout error every now and then which is thrown with a general error and I want to treat the timeout error differently than other errors within the same general error. I'm not sure what other type of errors could be thrown in the general error but I assume more of them exist. I have some sample code below of how I'm currently handling it, but I was thinking there might be a better way which I haven't found yet?
tries = 0
begin
tries += 1
<code>
rescue Foo::Bar => e
case e.to_s
when 'More specific timeout error message'
retry unless tries >= 5
else
# Let me see other error messages
log.info("Error: #{e.to_s}")
end
end
You can use multi rescue, to handle different errors.
begin
# DO SOMETHING
rescue Net::Timeout => e # change it to the error your want to catch, check the log.
# handle it
rescue SyntaxError => e # just an example
# handle it
rescue => e # any error that not catch by above rescue go here.
# handle it
end
Read more:
http://phrogz.net/programmingruby/tut_exceptions.html
You can try Rollbar, it help report error on production.
Take a look at retriable gem. It seems like a good fit for what you're proposing. Usually you'd rescue from an specific error type, but retriable also gives you the choice to rescue based on the error message.
begin
Retriable.retriable on: { Foo::Bar => /More specific timeout error message/ }, tries: 3 do
# will retry if an error of type Foo::Bar is raised
# and its message matches /More specific timeout error message/
# code here...
end
rescue => e # rescue for everything else
puts e.message # same as e.to_s
end
I am trying to rescue an aws s3 exception.
class FileManager
def fetchFile
begin
s3.get_object(bucket:'myBucket', key: file_name)
rescue Aws::S3::Errors => e
debugger
end
end
end
Then when I call the method from console
FileManager.fetch_file('Non existing file')
I am not getting the debugger instead there is an error message in the console
Aws::S3::Errors::NoSuchKey: The specified key does not exist.
I believe this has what your looking for (assuming you are using this gem):
https://github.com/marcel/aws-s3#when-things-go-wrong
You can rescue all S3 errors using ServiceError
begin
# ...
rescue Aws::S3::Errors::ServiceError => e
# ...
end
When exiting a Rails app using raise or fail, how to prevent the backtrace from being displayed?
Tried using back_trace_limit but it only seems to work for the console...?
You have total control over the backtrace returned with an exception instance by using its set_backtrace method. For example:
def strip_backtrace
yield
rescue => err
err.set_backtrace([])
raise err
end
begin
strip_backtrace do
puts 'hello'
raise 'ERROR!'
end
rescue => err
puts "Error message: #{err.message}"
puts "Error backtrace: #{err.backtrace}"
end
Output:
hello
Error message: ERROR!
Error backtrace: []
The strip_backtrace method here catches all errors, sets the backtrace to an empty array, and re-raises the modified exception.