Handle Ruby Exceptions With The Begin & Rescue Keywords

Let’s talk about “begin” & “rescue” in Ruby, two important keywords used for handling error conditions.

How do they work?

First, you need to understand something.

Your Ruby programs can trigger an error at multiple points while they’re running.

Examples include:

  • Trying to read a non-existing file
  • Dividing a number by zero
  • A web server you’re working with has an outdated SSL certificate

When that happens…

Ruby doesn’t crash right away!

You get a chance to handle & recover from the error.

We call this “exception handling”.

Ruby gives you a few keywords to implement error recovery in your code.

These keywords are begin & rescue.

Let’s discover how to use them!

How to Handle Ruby Exceptions

How do you handle these exceptions?

You can wrap the code that raises the exception with a begin / rescue block.

Here’s how that works…

The first section (begin), has the code that you’re going to run & that may raise an exception.


  # ...

We’re trying to open a file with sysopen.

An exception is raised if we can’t open the file.

This is where rescue comes in!

Here’s where you say what you want to happen when an exception is raised.


  puts "Can't open IO device."

You want to log this error & maybe provide some kind of default value.

Don’t. Ignore. Errors.

Rescuing Multiple Exceptions

You need to know that rescue takes an optional argument.

What is this argument?

This argument is the exception class that you want to rescue from.

It depends on what code you’re running.

For IO:

  • This may be Errno::ENOENT for a missing file
  • Or Errno::EACCES for a permission error

The best part?

You can handle multiple exceptions in the same begin/rescue block.

Like this:

rescue Errno::ENOENT
  puts "File not found."
rescue Errno::EACCES
  puts "Insufficient permissions, not allowed to open file."

If you want to have the same action happen for multiple exceptions…

You can do this:

rescue Errno::ENOENT, Errno::EACCES
  puts "There was an error opening the file."

Let’s keep learning!

How to Rescue Exceptions Inside Blocks & Methods

You don’t always have to use the begin keyword.

There are cases where you can leave it out.


Inside methods & blocks.


def get_null_device
rescue Errno::ENOENT
  puts "Can't open IO device."

The method definition itself does the work of begin, so you can omit it.

You can also do this with blocks.


["a.txt", "b.txt", "c.txt"].map do |f|
rescue Errno::ENOENT
  puts "Can't open IO device: #{f}."

Now, there is one more way to use the rescue keyword without begin.

Let’s see how that works.

Understanding Inline Rescue & Why Is It Dangerous

You can use rescue inline.

In a few rare scenarios, you may find this form of exception handling useful.

Here’s an example:

["a.txt", "b.txt", "c.txt"].select { |f| File.open(f) rescue nil }.map(&:size)

This allows you to open only the files that exist & ignore those that don’t.

As a result, you get the size for the existing files.

Without exceptions being raised.

Why do this?

Well, it lets you keep your code all in one line.

That’s about it.

There’s a “hidden danger” when using this form of rescue because you’re getting all exceptions descending from StandardError.

Which are most exceptions.

Why is that NOT good?

Because it’s best to only handle specific exceptions, instead of a broad selection of them.

This avoids hiding errors from yourself!

Hidden errors can lead to all kinds of strange behaviour & hard-to-debug issues.


You’ve learned about errors in Ruby, basic exception handling & the rescue / begin keywords.

Please share this article if you found it helpful 🙂

Thanks for reading!

Maimit Patel says last year

Hi, I want to buy Ruby Deep Dive book but I am based in Japan 🇯🇵 is it possible to buy this book in English in japan

    Jesus Castello says last year

    Yes, the book is in English, doesn’t matter where you buy it from 🙂

yura says last year

Example with “.map(&:size)” will return sizes of existing file names strings, not files.

Comments are closed