Greetings! We're working on an IronRuby project. There's a C# WPF application. We wrote a module for that application. When an error is raised in IronRuby, the application shows a message box. It only shows the error message. It does not show which Ruby script raised the error.
How do we get IronRuby to display the ruby file that raises the error?
I have found a workaround for this, you need to wrap your code with begin rescue like this:
begin
# Write your ruby code here, that can have an error
rescue SyntaxError, NameError => boom
str = "String doesn't compile:\n " + boom
puts str
puts boom.backtrace.join("\n")
rescue StandardError => bang
str = "Error running script: " + bang
puts str
puts bang.backtrace.join("\n")
rescue
puts "Unknown error happened"
end # rescues
Seem that Ruby interpreter throws an exception when error occurs, so you need to catch it and write its stack trace into messagebox. If you find another way, please write it here
Related
In the software called Roblox studio I need help making a script that whenever an error happens in game, it would print out the error again using the normal print function something like this example here:
Local error = —-whatever the error that happened was
Print(error) —- so it just simply prints it back out
Roblox provides a few different ways to keep track of when errors are thrown in your Scripts and LocalScripts.
If you want to observe errors locally in a script, and you know a specific chunk of code may throw errors, you can use pcall() as a try-catch block.
local success, result = pcall(function()
error("this is a test error message")
end)
if not success then
print("An error was thrown!")
print(result) --"this is a test error message"
end
If you want to observe errors across all of your scripts, you can attach a callback to the ScriptContext.Error signal. This signal fires any time any error is thrown. It provides information about the error, including the message, the callstack, and a reference to the script that threw the error.
Warning : ScriptContext.Error only fires in the context of the script that registers it. A Script will only observe errors thrown in server scripts, and registering in a LocalScript will only observe errors thrown on the client.
local ScriptContext = game:GetService("ScriptContext")
ScriptContext.Error:Connect( function(message, stack, context)
print("An error was thrown!")
print("Message : ", message)
print("Stack : ", stack)
print("Context :", context:GetFullName())
end)
Similarly, if you only care about the error messages themselves, you can also observe them being printed out to the Output window using the LogService.MessageOut signal. This signal fires any time anything is logged to Output. This includes messages, warnings, and errors.
local LogService = game:GetService("LogService")
LogService.MessageOut:Connect( function(message, messageType)
if messageType == Enum.MessageType.MessageError then
print("An error was thrown!")
print(message)
end
end)
Use the stderr stream from io library to print debug messages.
-- Define debug function based in print
function debug(...) io.stderr:write(table.concat({...}, '\9') .. '\n') end
-- Debug acts as a regular "print()", but it writes to stderr instead
debug('[filename.lua]', 'debug')
Use "error()" function to print errors.
if true then
error("It should not be true!")
end
If you want to catch errors from a function, use xpcall()
-- Define debug
function debug(...) io.stderr:write(table.concat({...}, '\9') .. '\n') end
xpcall(
function()
local b = {}
-- This will throw an error because you cant index nil values
print(a.b)
end,
function(err)
debug('[xpcall]', err)
end
)
xpcall() wont stop the execution in case of error, so you only need to encapsulate your code in it if you want to catch any unexpected errors at runtime.
I'm using the Slim Framework.
Most PHP errors in my application output normal PHP error messages
Example code with an error that outputs the Call Stack:
echo 'missing semicolon at eol'
Error Output:
Parse error: syntax error, unexpected T_IF, expecting ',' or ';' in /data/www/app/routes/companies_routes.php on line 737
Call Stack:
0.0002 637144 1. {main}() /data/www/html/index.php:0
But other errors ( maybe just notices ) output a limited message that doesn't have a line number, file name, or call stack. This makes debugging these errors extremely time consuming.
Code with an error that outputs a limited error message
echo $an_undefined_variable;
Limited Message
Undefined variable: an_undefined_variable
I can't figure out what's going on. I've never had this problem before. I suspect it has something to do with the way Slim handles PHP errors. I've tried wrapping these errors in Try/Catch blocks, but that doesn't solve the problem.
The problem is that Slim is handling exceptions itself ( some sort of default behavior I've yet to track down ).
I've got my code wrapped in Try/Catch blocks, so when Slim catches a PHP error, it's throwing it's own Exception that I'm then outputting in my Catch block. If I remove my Catch block, Slim them outputs it's own complete error message that contains the stack as usual.
This surely means I'm not using Slim quite right, but that's a different question.
I have an iteration in which I am calling set_table_name for some model. The idea is that in each iteration, the model changes its table. Sometimes, the table won't exist, in that case, an error of this kind will happen:
Mysql2::Error: Table 'db_name.table_name_xyz' doesn't exist
I want the iteration to keep running and not abort because of the error. I've wrapped the set_table_name line of code with a begin and rescue, but no exception seems to be raised as the script instantly aborts on error (it doesn't execute the rescue code). Here's the code:
((start_year)..(start_actual_year)).each do |year|
begin
Data.set_table_name("Secciones#{year}#{year + 1}")
rescue Exception => e
next
end
end
Can I rescue this kind of error? What should I do? Thanks!
Are you sure you are catching the exception correctly? Here's more info if needed.
begin
# Your code here.
rescue Exception => e
# Output the exception that it is catching.
puts e.message
ensure
# The ensure block is used to close a db connection if needed.
end
I have an rspec test that I expect to fail, but it is passing because the code that it is testing rescues the exception that rspec raises. Here's an example of the situation:
class Thing do
def self.method_being_tested( object )
# ... do some stuff
begin
object.save!
rescue Exception => e
# Swallow the exception and log it
end
end
end
In the rspec file:
describe "method_being_tested" do
it "should not call 'save!' on the object passed in" do
# ... set up the test conditions
mock_object.should_not_receive( :save! )
Thing.method_being_tested( mock_object )
end
end
I knew that the execution was reaching the "object.save!" line of the method being tested, and the test should therefore be failing, but the test passes. Using the debugger in the rescue block, I find the following:
(rdb:1) p e # print the exception object "e"
#<RSpec::Mocks::MockExpectationError: (Mock "TestObject_1001").save!
expected: 0 times
received: 1 time>
So basically the test is failing but, but the failure is being suppressed by the very code it is trying to test. I cannot figure out a viable way to stop this code from swallowing Rspec exceptions without somehow compromising the code. I don't want the code to explicitly check if the exception is an Rspec exception, because that is bad design (tests should be written for code, code should never be written for tests). But I also can't check that the exception is any particular type that I DO want it to catch, because I want it to catch ANYTHING that could be raised in a normal production environment.
Someone must have had this problem before me! Please help me find a solution.
Assuming the code is correct as-is:
describe "method_being_tested" do
it "should not call 'save!' on the object passed in" do
# ... set up the test conditions
calls = 0
mock_object.stub(:save!) { calls += 1 }
expect {Thing.method_being_tested(mock_object)}.to_not change{calls}
end
end
If there's no need to catch absolutely all exceptions including SystemExit, NoMemoryError, SignalException etc (input from #vito-botta):
begin
object.save!
rescue StandardError => e
# Swallow "normal" exceptions and log it
end
StandardError is the default exception level caught by rescue.
from rspec-mock:
module RSpec
module Mocks
class MockExpectationError < Exception
end
class AmbiguousReturnError < StandardError
end
end
end
Do you really need to catch Exception? Could you catch StandardError instead?
Catching all exceptions is generally a bad thing.
I would refactor it like so:
class Thing do
def self.method_being_tested!( object )
# ... do some stuff
return object.save
end
end
If you want to ignore the exception thrown by save! there is no point in calling save! in the first place. You just call save and inform the calling code accordingly.
I'd like ExceptionNotifier to send out an email when an exception happens in a delayed job, just like for other exceptions. How can I achieve that?
I do this with Rails 3.2.6, delayed_job 3.0.3 and exception_notification 2.6.1 gem
# In config/environments/production.rb or config/initializers/delayed_job.rb
# Optional but recommended for less future surprises.
# Fail at startup if method does not exist instead of later in a background job
[[ExceptionNotifier::Notifier, :background_exception_notification]].each do |object, method_name|
raise NoMethodError, "undefined method `#{method_name}' for #{object.inspect}" unless object.respond_to?(method_name, true)
end
# Chain delayed job's handle_failed_job method to do exception notification
Delayed::Worker.class_eval do
def handle_failed_job_with_notification(job, error)
handle_failed_job_without_notification(job, error)
# only actually send mail in production
if Rails.env.production?
# rescue if ExceptionNotifier fails for some reason
begin
ExceptionNotifier::Notifier.background_exception_notification(error)
rescue Exception => e
Rails.logger.error "ExceptionNotifier failed: #{e.class.name}: #{e.message}"
e.backtrace.each do |f|
Rails.logger.error " #{f}"
end
Rails.logger.flush
end
end
end
alias_method_chain :handle_failed_job, :notification
end
It's probably a good idea to load this code in all environments to catch errors after bundle update etc before they reach production. I do this by having a config/initializers/delayed_job.rb file but you could duplicate the code for each config/environments/* environment.
Another tip is to tune the delayed job config a bit as default you may get a lot of duplicate exception mails when job fails.
# In config/initializers/delayed_job_config.rb
Delayed::Worker.max_attempts = 3
Update I had some problems with the delayed_job daemon silently exiting and it turned out to be when ExceptionNotifier fails to send mail and no one rescued the exception. Now the code rescues and log them.
Adding to #MattiasWadman answer, since exception_notification 4.0 there's a new way to handle manual notify. So instead of:
ExceptionNotifier::Notifier.background_exception_notification(error)
use
ExceptionNotifier.notify_exception(error)
Another way to handle exceptions (put as an initializer):
class DelayedErrorHandler < Delayed::Plugin
callbacks do |lifecycle|
lifecycle.around(:invoke_job) do |job, *args, &block|
begin
block.call(job, *args)
rescue Exception => e
# ...Process exception here...
raise e
end
end
end
end
Delayed::Worker.plugins << DelayedErrorHandler
alias_method_chain no longer exists in Rails 5.
Here's the new (proper) way to do this using Ruby 2's prepend
# In config/initializers/delayed_job.rb
module CustomFailedJob
def handle_failed_job(job, error)
super
ExceptionNotifier.notify_exception(error, data: {job: job})
end
end
class Delayed::Worker
prepend CustomFailedJob
end
For exception_notification 3.0.0 change:
ExceptionNotifier::Notifier.background_exception_notification(error)
to:
ExceptionNotifier::Notifier.background_exception_notification(error).deliver
simpler and updated answer:
# Chain delayed job's handle_failed_job method to do exception notification
Delayed::Worker.class_eval do
def handle_failed_job_with_notification job, error
handle_failed_job_without_notification job, error
ExceptionNotifier.notify_exception error,
data: {job: job, handler: job.handler} rescue nil
end
alias_method_chain :handle_failed_job, :notification
end
And test on console with:
Delayed::Job.enqueue (JS=Struct.new(:a){ def perform; raise 'here'; end }).new(1)