Ruby handles errors with begin/rescue/ (Ruby's equivalent of try/catch/finally). You exceptions and them, with for cleanup. Ruby also allows method-level rescue (without explicit ) for cleaner code.
Ruby handles errors with begin/rescue/ (Ruby's equivalent of try/catch/finally). You exceptions and them, with for cleanup. Ruby also allows method-level rescue (without explicit ) for cleaner code.
ensureraiserescueensurebeginbegin
result = risky_operation
rescue ArgumentError => e # rescue a SPECIFIC exception type
puts "Bad argument: #{e.message}"
rescue StandardError => e # broader catch (StandardError, not Exception)
puts "Error: #{e.message}"
retry if attempts < 3 # retry can re-run the begin block
else
puts "succeeded" # runs if NO exception
ensure
cleanup # ALWAYS runs (success or failure)
end
begin/rescue/ensure is Ruby's try/catch/finally. Rescue specific types (rescue ArgumentError), use ensure for guaranteed cleanup, and else for the no-error case. retry can re-attempt the block.
rescue => e # ✅ bare rescue catches StandardError (the right default)
rescue StandardError # ✅ explicit, same thing
rescue Exception # ❌ AVOID — catches EVERYTHING including system signals
# (Interrupt/Ctrl-C, SystemExit) — can break the program
Important: a bare rescue catches StandardError (the correct default for application errors). Rescuing Exception (the root) catches everything, including system-level signals like Interrupt (Ctrl-C) and SystemExit — which you usually don't want to catch, as it can prevent the program from being interrupted or exiting properly. A common Ruby mistake.
raise ArgumentError, "Amount must be positive" # raise a built-in
raise "Something failed" # raises RuntimeError
# custom exception class
class InsufficientFundsError < StandardError # inherit from StandardError
def initialize(msg = "Not enough funds")
super
end
end
raise InsufficientFundsError
def process
do_work
rescue => e # rescue WITHOUT begin — applies to the whole method body
handle(e)
ensure
cleanup
end
Proper exception handling is essential for robust Ruby applications, and understanding Ruby's approach — including its specific idioms and caveats — is important.
The begin/rescue/ensure structure (Ruby's try/catch/finally), rescuing specific exception types, using ensure for guaranteed cleanup, and the clean method-level rescue (without explicit begin) are fundamental everyday knowledge.
A particularly important and distinctly Ruby point is the StandardError vs Exception distinction: a bare rescue (and the correct default) catches StandardError, but rescuing Exception (the root of the hierarchy) catches everything — including system signals like Interrupt (Ctrl-C) and SystemExit — which you almost never want, since it can prevent the program from being interrupted or exiting properly, and is a common, harmful mistake.
Understanding that you should rescue StandardError (not Exception) for application errors is important Ruby-specific knowledge that prevents real bugs.
Knowing the structure, custom exception classes (inheriting from StandardError), retry, the method-level rescue idiom, and especially the StandardError-not-Exception caveat is important for writing robust, correct Ruby that handles errors gracefully without breaking the program's ability to be interrupted.
Since unhandled errors and the Exception-rescuing mistake both cause real problems, mastering Ruby's exception handling — its structure, idioms, and the critical StandardError vs Exception distinction — is important, frequently-relevant knowledge for reliable Ruby development and a common interview topic.