Blog |

Ruby Exception Handling – Primer for Dealing with Errors in Ruby

Ruby Exception Handling – Primer for Dealing with Errors in Ruby
Table of Contents

Ruby is a popular open source programming language that is highly flexible, and used for everything from basic "hello world" apps to sophisticated, dynamic programs. Whether you've been programming in Ruby for years or you're a complete beginner, tracking down errors in your Ruby app is simple and easy. Let's go through some basic Ruby error handling, and discover how easy it can be to integrate Rollbar into your Ruby app to automatically log and report your exceptions.

Raise and Rescue Exceptions

Ruby's default exception handling is to terminate the program in the event of an exception. That's not really useful when you're trying to build a complex web application for multiple users. Luckily there's a way around this - declaring exception handlers. Exception handlers are blocks of code that are called if an exception occurs in the execution of another block of code in your program. For the most basic Ruby exception handling, you need to know how to Raise and Rescue an exception.

When you Raise an exception, you stop the normal flow of the program, and execute the code that deals with handling an error. This code can either deal with the error in some way, or terminate the program. If you provide a Rescue clause in your error handler, you can choose how to deal with the exception; without it, the program will simply terminate.

Ruby Exception Hierarchy

Ruby has a predefined Exception class, with quite a few subclasses that can be used for basic error handling. The hierarchy of these subclasses is as follows (with commentary):

  • Fatal: used internally by Ruby when it must exit due to a fatal error. Errors of this class can't be rescued.
  • NoMemoryError: raised when memory allocation fails.
  • ScriptError: used when a script is unable to be executed. This can be due to errors in any of the subclasses of ScriptError.
    • LoadError: raised if a required file doesn't load.
    • NotImplementedError: raised when a feature isn't implemented on the current platform (i.e., trying to call a method that isn't supported by the operating system).
    • SyntaxError: occurs when trying to execute code with invalid syntax.
  • SecurityError: raised when a potentially unsafe operation is attempted.
  • SignalException: used when a signal is received on a process.
    • Interrupt: raised if the interrupt signal is received (i.e., a user pressed Ctrl-C).
  • StandardError: used for the most common types of exceptions. Usually the subclasses will be raised rather than StandardError itself. However, when a rescue clause without a specific StandardError subclass is executed, StandardError will be raised.
    • ArgumentError: occurs when arguments are incorrect (i.e., the wrong number of arguments).
    • FiberError: raised if an invalid operation is being attempted on a Fiber (i.e., trying to call a dead Fiber).
    • IndexError: used when the index is invalid.
    • KeyError: occurs if a specified key is not found.
    • StopIteration: raised to stop the iteration.
    • IOError: raised during an input/output operation failure.
    • EOFError: occurs when reaching the end of the file by some IO operations.
    • LocalJumpError: raised if Ruby cannot yield as requested in the code.
    • NameError: raised if a name is undefined or invalid.
    • NoMethodError: used when a method is called on a receiver that doesn't have the method defined, and the receiver doesn't respond with method_missing.
    • RangeError: raised if a numerical value is out of range.
    • FloatDomainError: occurs when attempting to convert certain float values to unsupported classes.
    • RegexpError: raised if a given regular expression is invalid.
    • RuntimeError: used when given an invalid operation. This is a generic error class.
    • SystemCallError: raised for low-level, platform-dependent errors. These exceptions look like Errno:xxx.
    • ThreadError: occurs if an invalid operation is being attempted on a Thread.
    • TypeError: raised when an object is not of the expected type.
    • ZeroDivisionError: used if attempting to divide an integer by 0.
  • SystemExit: raised if the exit method is called to terminate the script.
  • SystemStackError: occurs during a stack overflow (i.e., in the case of an accidental infinite loop).

Basic Ruby Error Handling

Okay, so now we know what Ruby's exception hierarchy looks like, and why we need to Raise and Rescue our application's exceptions. But how do you actually do this? If you're a beginner or just new to Ruby, this might all sound fantastic in theory, but you need to see some code to actually understand what you're supposed to do.

Here's an example program that handles an exception:

def handle_exception
    puts 'Lalala, our app is running without errors.'
    raise 'Oh no, a error has occurred.'
  rescue
    puts 'Hooray the error has been rescued instead of terminating the program.'
end

handle_exception

Level Up: Ruby + Rollbar = ❤️

So far, so good. We've got our Ruby error handling down, and we're feeling like old pros. 🙂 But let's say you want to keep track of the errors that are occurring in your application, maybe even get some alerts when a certain number of exceptions are raised. What do you do? You could write some custom code and try to do this all yourself...or you could simply integrate your application with Rollbar and set your error handling, logging, and alerting on auto-pilot.

Getting Started with Rollbar

To get started, you'll need to sign up for a Rollbar account and name and create the new Ruby 'project' you will be monitoring with Rollbar. You get two weeks free when you sign up, so you can see if Rollbar is right for you.

Once you've signed up for an account you'll receive a server-side access token which you'll need to save for later.

Installing the Gem

Installing the Gem is super easy! First, add this line to your application's Gemfile:

gem 'rollbar'

And then execute:

$ bundle install

If you don't use bundler, execute this instead:

$ gem install rollbar

Unless you are using JRuby, we suggest also installing Oj for JSON serialization. Add this line to your Gemfile:

gem 'oj', '~> 2.12.14'

and then run bundle install again.

Basic Ruby Integration

Rollbar isn't dependent on Rack or Rails for most of its functionality, but if you're using Rack or Rails, there is more info on using both of these Ruby frameworks below. In a plain Ruby project, assuming you've installed the Rollbar gem, you just need to do these three easy steps:

  1. Require Rollbar
  2. Configure Rollbar
  3. Send Rollbar data
require 'rollbar'

Rollbar.configure do |config|
  config.access_token = "POST_SERVER_ITEM_ACCESS_TOKEN"
  # Any other configuration settings you might wish to have
end

Rollbar.debug("Running Script")

begin
  run_script ARGV
rescue Exception => e # Never rescue Exception *unless* you reraise in rescue body
  Rollbar.error(e)
  raise e
end

Rollbar.info("Script ran successfully")

See the configuration reference guide on GitHub for further information on more advanced settings and granular configuration settings.

Using Rails

Run the following command from your Rails root:

$ rails generate rollbar POST_SERVER_ITEM_ACCESS_TOKEN

Be sure to replace POST_SERVER_ITEM_ACCESS_TOKEN with your project's post_server_item access token, which you can find in the Rollbar.com interface.

That will create the file config/initializers/rollbar.rb, which initializes Rollbar and holds your access token and other configuration values.

If you want to store your access token outside of your repo, run the same command without arguments and create an environment variable ROLLBAR_ACCESS_TOKEN that holds your server-side access token:

$ rails generate rollbar
$ export ROLLBAR_ACCESS_TOKEN=POST_SERVER_ITEM_ACCESS_TOKEN

For Heroku users:

If you're on Heroku, you can store the access token in your Heroku config:

$ heroku config:add ROLLBAR_ACCESS_TOKEN=POST_SERVER_ITEM_ACCESS_TOKEN

Using Sinatra

Initialize Rollbar with your access token somewhere during startup:

Rollbar.configure do |config|
  config.access_token = 'POST_SERVER_ITEM_ACCESS_TOKEN'
  config.disable_rack_monkey_patch = true
  # other configuration settings
  # ...
end

Then mount the middleware in your app, like:

require 'rollbar/middleware/sinatra'

class MyApp < Sinatra::Base
  use Rollbar::Middleware::Sinatra
  # other middleware/etc
  # ...
end

Using Other Rack Frameworks

Initialize Rollbar with your access token somewhere during startup:

Rollbar.configure do |config|
  config.access_token = 'POST_SERVER_ITEM_ACCESS_TOKEN'
  # other configuration settings
  # ...
end

Be sure to replace POST_SERVER_ITEM_ACCESS_TOKEN with your project's post_server_item access token, which you can find in the Rollbar.com interface.

The gem monkey patches Rack::Builder so Rollbar reports will be sent automatically without any other action. If you prefer to disable the monkey patch, apply this change to your config::

Rollbar.configure do |config|
  config.disable_rack_monkey_patch = true
  # other configuration settings
  # ...
end

If you disabled the Rack::Builder monkey patch or it doesn't work for the Rack framework you are using, then add our Rack middleware to your app:

require 'rollbar/middleware/rack'

use Rollbar::Middleware::Rack

Test Your Installation

If you're not using Rails, you may first need to add the following to your Rakefile:

require 'rollbar/rake_tasks'

You may also need to add an :environment task to your Rakefile if you haven't already defined one. At minimum, this task should call Rollbar.configure() and set your access token.

task :environment do
  Rollbar.configure do |config |
    config.access_token = '...'
  end
end

To confirm that it worked, run:

$ rake rollbar:test

This will raise an exception within a test request; if it works, you'll see a stacktrace in the console, and the exception will appear in the Rollbar dashboard.

Integration with Rollbar.js

The gem has a cool feature - you can configure the gem to enable Rollbar.js on your site to report your JavaScript errors using Rollbar.js.

Rollbar.configure do |config|
  # common gem configuration
  # ...
  config.js_enabled = true
  config.js_options = {
    accessToken: "POST_CLIENT_ITEM_ACCESS_TOKEN",
    captureUncaught: true,
    payload: {
      environment: "production"
    }
  }
end

The Hash passed to #js_options= should have the same available options that you can find in Rollbar.js, using symbols or strings for the keys.

For further information, you'll want to check out the gem docs for advanced ways to use the gem.

Diagnosing and debugging Ruby errors with Rollbar

Now that you have Rollbar integrated into your Ruby application, any errors that occur will be automatically captured and viewable from your dashboard and errors page within Rollbar (screenshot below). You'll be able to easily see what errors are occurring, how often they occur and the full context and analytics into your Ruby applications errors. Rollbar provides a detailed stack trace of every ruby exception allowing you to see exactly what's happening in your application when an error occurs. You can also view the user's browser and OS where the error occurred.

ruby exception handling with rollbar

Errors are grouped by cause and frequency so that you can prioritize which ones to work on first. You'll be able to view trends over time. If a certain error spikes in frequency, you'll know about it right away. Below are more features worth noting:

  • Errors automatically get grouped by root cause.
  • Tons of context data like stack traces, request params, URL and environment.
  • Integrate your favorite tools like Slack, GitHub, JIRA, Pivotal Tracker, Trello, PagerDuty.
  • Tons of context data like stack traces, request params, URL and environment.
  • View trends by type of error, browser, code deployment, OS, location, users, host.
  • Mark an item as Resolved, Mute or Assign errors to others on your team to fix.
  • Keep track of code deployments and correlate them them to new error occurrences.

With Rollbar, you can rest assured that you'll know about any bugs that might make their way into your Ruby projects. If you run into any issues, we're always available to help at [email protected]. Happy hacking!

"Rollbar allows us to go from alerting to impact analysis and resolution in a matter of minutes. Without it we would be flying blind."

Error Monitoring

Start continuously improving your code today.

Get Started Shape