Exceptions are Ruby’s built-in way of handling errors and unexpected situations without crashing your program. Instead of checking every possible failure manually, Ruby lets you rescue exceptions, handle them gracefully, and keep your application stable.
This tutorial walks through Ruby exceptions step by step, with clear explanations and practical code examples.
Table of Contents
1) What Are Exceptions in Ruby?
An exception is an object that represents an error condition, such as:
- Dividing by zero
- Accessing a file that doesn’t exist
- Calling a method on
nil
When an exception occurs, Ruby raises it and looks for a matching rescue block.
Example:
puts 10 / 0
# => ZeroDivisionError
2) Basic Exception Handling (begin / rescue)
Simple rescue block
begin
result = 10 / 0
rescue
puts "Something went wrong"
end
This prevents the program from crashing.
Rescuing a specific exception
begin
result = 10 / 0
rescue ZeroDivisionError
puts "You cannot divide by zero"
end
Best practice: always rescue specific exceptions when possible.
3) Accessing the Exception Object
You can capture the exception object for debugging or logging.
begin
File.read("missing.txt")
rescue Errno::ENOENT => e
puts "Error: #{e.message}"
end
Output:
Error: No such file or directory @ rb_sysopen - missing.txt
4) Multiple rescue Clauses
Handle different errors in different ways.
begin
puts 10 / value
rescue ZeroDivisionError
puts "Division by zero"
rescue NameError
puts "Variable not defined"
end
5) Using else and ensure
else (runs if no exception occurs)
begin
result = 10 / 2
rescue ZeroDivisionError
puts "Error"
else
puts "Result is #{result}"
end
ensure (always runs)
file = File.open("example.txt", "w")
begin
file.puts "Hello"
rescue IOError
puts "Write failed"
ensure
file.close
end
ensure is commonly used for cleanup tasks like closing files or releasing resources.
6) Raising Exceptions Manually (raise)
You can raise your own exceptions when something is invalid.
def withdraw(amount)
raise ArgumentError, "Amount must be positive" if amount <= 0
puts "Withdrawing #{amount}"
end
withdraw(-10)
7) Custom Exception Classes
Define your own exception types by inheriting from StandardError.
class InsufficientFundsError < StandardError
end
def withdraw(balance, amount)
raise InsufficientFundsError, "Not enough balance" if amount > balance
balance - amount
end
begin
withdraw(100, 200)
rescue InsufficientFundsError => e
puts e.message
end
8) Retry Logic with retry
retry allows you to attempt an operation again after rescuing an error.
attempts ||= 0
begin
attempts += 1
puts "Attempt #{attempts}"
raise "Temporary failure"
rescue
retry if attempts < 3
end
Use retry carefully to avoid infinite loops.
9) Implicit Rescue in Methods
Ruby allows a short form rescue inside methods.
def safe_divide(a, b)
a / b
rescue ZeroDivisionError
nil
end
puts safe_divide(10, 0)
This is concise but should be used sparingly for clarity.
10) Exception Hierarchy (Quick Overview)
Most common exceptions inherit from StandardError.
Exception
├── StandardError
│ ├── ArgumentError
│ ├── RuntimeError
│ ├── ZeroDivisionError
│ └── NameError
└── SystemExit
Avoid rescuing Exception directly—it can hide serious system-level issues.
11) Best Practices for Ruby Exceptions
- Rescue specific exceptions
- Use
ensurefor cleanup - Raise meaningful error messages
- Avoid using exceptions for normal control flow
- Log or report errors in production systems
FAQ (for Rich Results)
Q: What is exception handling in Ruby? A: Exception handling lets Ruby programs handle runtime errors gracefully using begin, rescue, and ensure.
Q: How do I raise an exception in Ruby? A: Use raise, for example raise ArgumentError, "Invalid value".
Q: Should I rescue Exception in Ruby? A: No. Always rescue specific exceptions or StandardError to avoid hiding critical system errors.