Ruby Exception Handling

Ruby Exception Handling: RuntimeError

Making our way through our Ruby Exception Handling series our next stop brings us to the default raised exception class in Ruby, the RuntimeError. A RuntimeError is raised when attempting to perform an invalid operation of some kind, which doesn’t meet the criteria of a more specific error classification.

In this article we’ll bust through the cracks of the RuntimeError, exploring where it sits within the Ruby Exception class hierarchy, as well as go over a few simple code examples that help to illustrate how RuntimeErrors are raised in the first place. Let’s dig in!

The Technical Rundown

  • All Ruby exceptions are descendants of the Exception class, or a subclass therein.
  • StandardError is a direct descendant of the Exception class, and is also a superclass with many descendants of its own.
  • RuntimeError is the direct descendant of StandardError.

When Should You Use It?

Most programming languages loosely define a runtime error as an exception that occurs during the runtime (execution) of the application. While that’s not all that useful of a definition, it can easily be distinguished from other categories of exceptions such as compilation errors, which are caught by the compiler of the language in question before execution even occurs. For example, an error from incorrect syntax would not be considered a runtime error since it will be caught by the compiler before execution. We saw this in our article exploring Ruby’s SyntaxError using the following example code:

That said, even in the realm of runtime errors things tend to be a little confusing since most languages provide dozens if not hundreds, as is the case with .NET, of built-in classes to handle specific runtime exceptions. Ruby is no different, with specific errors that we’ve seen before like the RegexpError and the LocalJumpError. However, since Ruby cannot inherently provide a specific class for every possible type of runtime error that might occur there must be a fallback and that’s where the RuntimeError class comes in.

Perhaps the most important property of RuntimeError — something that makes it unique among the dozens of other error classes in Ruby — is that RuntimeError is the default error class that is used when calling the standard Kernel#raise method that we all use to handle exceptions. While Kernel#raise allows us to provide a specific error class which to raise, opting not to specify a class means Ruby will create an instance of RuntimeError.

For example, here we have a somewhat real-world example of a Book class with a custom setter for the Book#page_countproperty within which the value is checked and if it’s less than 1000 pages everything is OK. But, if it’s greater than 1000 pages it is outside the allowed bounds and we raise a RangeError:

Now when we create a new instance of Book we check the page_count value provided and either raise a RangeError or can continue execution as normal if no error occurs. This gives us a few illustrating examples:

In the first example our book is too long so we raise a RangeError. In the second example we don’t raise an error during creation of our book, so we get to explicitly raise a RuntimeError. Finally, in the third example our book remains short enough so there’s no RangeError, however we’re not specifying what type of error to raise so it still defaults to RuntimeError. The output for all three of these functions shows the expected error list:

Outside of raising a RuntimeError, either explicitly or indirectly, it’s also possible for them to occur during normal execution when an invalid operation occurs. One such instance where a RuntimeError may be raised is when trying to modify an immutable object like a frozen string. For those who may unfamiliar, Ruby provides the Object#freeze method that allows us to explicitly convert a normally mutable object to an immutable. For example, in this snippet we declare a name string variable, add something to it, then output the full string. We then try that same pattern again, but the second time we explicitly freeze our string variable before trying to modify it:

As you might expect the first round works fine but the second round raises a RuntimeError because we’re trying to modify an immutable string:

To get the most out of your own applications and to fully manage any and all Ruby Exceptions, check out the Airbrake Ruby exception handling tool, offering real-time alerts and instantaneous insight into what went wrong with your Ruby code, including integrated support for a variety of popular Ruby gems and frameworks.