Exception Handling in Ruby
Gracefully manage errors with begin/rescue/ensure and custom exceptions.
Basics and hierarchy
Wrap risky code in begin/rescue; ensure always runs. Most application errors inherit from StandardError.
begin
risky()
rescue StandardError => e
warn e.message
ensure
cleanup()
end
Rescue specific exceptions
Rescue the narrowest class you can; multiple rescues are allowed. A bare rescue catches StandardError only (not Exception).
begin
Integer("x")
rescue ArgumentError
:bad_input
rescue => e # StandardError and subclasses
:unknown
end
Else and ensure
else runs only if no exception was raised; ensure runs regardless.
begin
result = compute()
else
log_success(result)
ensure
close_resources()
end
Retry (use cautiously)
You can retry the begin block from within a rescue—avoid infinite loops; add backoff/limits.
attempts = 0
begin
attempts += 1
fetch()
rescue TimeoutError
retry if attempts < 3
end
Raising and custom errors
Raise built-ins or your own subclasses of StandardError.
class NotFound < StandardError; end
def fetch!(id)
raise NotFound, "id=#{id}" unless exists?(id)
find(id)
end
Inline rescue
Useful for small guards; don’t overuse because it can hide errors.
value = Integer(param) rescue nil
Backtraces and logging
Use e.backtrace (array of strings) to log stack traces; prefer structured logging when possible.
Summary
- Rescue specific exceptions; avoid blanket catches
- Use
ensurefor cleanup andelsefor success-only paths; considerretrywith caution - Define custom errors for domain-specific failures; raise informative messages