Lesson 9 of 11
Error Handling
Learn how to raise and rescue so your program can recover from errors. `begin/rescue/ensure` works like try/catch/finally in other languages.
# Basic rescue
begin
result = 10 / 0
rescue ZeroDivisionError => e
puts "Caught: #{e.message}" # Caught: divided by 0
end
# Multiple rescue clauses
def parse_input(input)
begin
Integer(input) # raises ArgumentError if not a valid integer
rescue ArgumentError
puts "Not a valid integer"
nil
rescue TypeError
puts "Wrong type entirely"
nil
end
end
# else — runs if no exception raised
# ensure — always runs (like finally)
def read_file(path)
f = File.open(path)
content = f.read
rescue Errno::ENOENT => e
puts "File not found: #{e.message}"
nil
else
puts "Read #{content.length} bytes successfully"
content
ensure
f&.close # &. is the safe navigation operator — only calls close if f is not nil
end# Custom exceptions
class InsufficientFundsError < StandardError
attr_reader :amount, :balance
def initialize(amount, balance)
@amount = amount
@balance = balance
super("Cannot withdraw $#{amount}. Current balance: $#{balance}")
end
end
class BankAccount
def initialize(balance)
@balance = balance
end
def withdraw(amount)
raise ArgumentError, "Amount must be positive" unless amount > 0
raise InsufficientFundsError.new(amount, @balance) if amount > @balance
@balance -= amount
@balance
end
end
account = BankAccount.new(100)
begin
account.withdraw(200)
rescue InsufficientFundsError => e
puts e.message
puts "Tried to withdraw: $#{e.amount}"
rescue ArgumentError => e
puts "Bad input: #{e.message}"
end
# retry — re-attempt the begin block
attempts = 0
begin
attempts += 1
raise "Temporary error" if attempts < 3
puts "Succeeded on attempt #{attempts}"
rescue RuntimeError
retry if attempts < 3
puts "Failed after 3 attempts"
endFinished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.