Ruby Programming
Coding Style
Error Handling
Exception Handling
Programming Best Practices

Why is it bad style to `rescue Exception => e` in Ruby?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Ruby, rescuing Exception is usually considered bad style because it catches far more than ordinary application errors. Exception sits at the top of Ruby's exception hierarchy, so rescuing it can swallow failures that your program generally should not try to recover from.

The normal target for application-level rescue logic is StandardError or, even better, a more specific subclass. That keeps error handling focused on the problems you actually expect and know how to address.

Why Exception Is Too Broad

When you write:

ruby
1begin
2  dangerous_operation
3rescue Exception => e
4  puts "caught: #{e.message}"
5end

you are not just catching business-level failures such as bad input or missing files. You are also catching system-level conditions and control-flow exceptions that may need to escape.

Examples include:

  • 'SystemExit, raised by exit'
  • 'Interrupt, raised for things such as Ctrl+C'
  • 'NoMemoryError'
  • 'SignalException'

Catching all of those can make a program ignore shutdown requests, hide serious runtime problems, or continue in a state it was never meant to survive.

Rescue StandardError Instead

Ruby's default rescue without an explicit class already rescues StandardError, which is usually what you want:

ruby
1begin
2  file = File.open("somefile.txt", "r")
3  contents = file.read
4rescue StandardError => e
5  puts "an error occurred: #{e.message}"
6ensure
7  file.close if file
8end

This catches the ordinary exceptions most application code is expected to handle while still letting more severe exceptions propagate.

In many cases you do not even need to write StandardError explicitly:

ruby
1begin
2  risky_call
3rescue => e
4  puts e.message
5end

That still targets StandardError.

Rescue Specific Exceptions When Possible

Even StandardError can be broader than necessary. If you know which failure you expect, rescue that class directly:

ruby
1begin
2  File.read("config.yml")
3rescue Errno::ENOENT
4  puts "config file is missing"
5end

This is better because it documents intent. The reader can immediately see what problem the code is prepared to recover from.

Specific rescue clauses also make it harder to hide unrelated bugs by accident.

Broad Rescue Can Hide Real Bugs

Imagine this code:

ruby
1def process_order(order)
2  begin
3    total = order.line_items.sum(&:price)
4    charge_customer(total)
5  rescue Exception => e
6    log_error(e)
7    false
8  end
9end

If there is a programming bug inside charge_customer, or the process receives an interrupt during shutdown, this code turns those events into a generic false return value. That makes diagnosis harder and can leave the system in a misleading state.

Broad rescue blocks often feel safe while actually making failures less visible.

Know When Broad Rescue Is Justified

There are rare top-level boundaries where a broader rescue may be justified, such as a process supervisor that logs fatal crashes before exiting. Even there, you should be deliberate:

ruby
1begin
2  run_service
3rescue Exception => e
4  warn("fatal: #{e.class}: #{e.message}")
5  raise
6end

The key difference is that this pattern logs and re-raises. It does not pretend the program can safely continue after every possible exception.

Common Pitfalls

The biggest mistake is using rescue Exception as a generic "make sure nothing crashes" pattern. That usually hides bugs rather than fixing them.

Another common issue is catching Interrupt, which makes CLI programs harder to stop and surprises operators during deployment or debugging.

People also rescue broadly and then return nil, false, or a default object. That turns very different failures into the same result and makes the code much harder to reason about.

Finally, rescuing a broad class far away from the actual failing call often mixes unrelated concerns. Error handling is better when it is close to the operation whose failure you understand.

Summary

  • 'Exception is the root of Ruby's exception hierarchy, so rescuing it is usually too broad.'
  • Application code should normally rescue StandardError or a more specific exception class.
  • Broad rescue can swallow interrupts, exits, and other conditions that should usually propagate.
  • Rescue specific exceptions when you know the expected failure mode.
  • If you must rescue broadly at a top-level boundary, log and re-raise instead of pretending everything is recoverable.

Course illustration
Course illustration

All Rights Reserved.