# Handling many networking exceptions in Ruby

What would be a prettier/faster way to do handling of multiple errors in Ruby? Here is the code I am working with:

begin
response = session.get url
rescue Patron::HostResolutionError
puts "Error resolving remote host."
exit 1
rescue Patron::PartialFileError
puts "File size mismatch. (Host reported a file size, but the actual file is of different size)"
exit 1
rescue Patron::TimeoutError
puts "Operation timed out."
exit 1
rescue Patron::TooManyRedirects
puts "Tried redirecting too many times."
exit 1
rescue Patron::URLFormatError
puts "Error with the URL format"
exit 1
rescue Patron::UnsupportedProtocol
puts "This URL is using a protocol that we cannot handle."
exit 1
rescue Patron::ConnectionFailed
puts "Error connecting to host. Check your internet connection."
exit 1
end


Since you're rescuing all 7 subclasses of Patron::Error, it would make sense to directly rescue Patron::Error rather than rescuing them one by one.

You're also duplicating work that has already been done for you, by formulating your own error message for each exception: the exceptions will already contain a useful error message, which even contains more information than yours do (for example if the host could not be resolved, the exception's message will contain the hostname that could not be resolved instead of just saying "Error resolving remote host").

Lastly I would print error messages to stderr, not stdout, as that's where they're supposed to go.

So I would write the code like this:

begin
response = session.get url
rescue Patron::Error => e
\$stderr.puts e.message
exit 1
end


Your begin/rescue code does look repetitive, but on the hand it would be easy to extend in the future. If you are certain you will always have this structure (rescue with an error message + exit), you can abstract it, for example:

exceptions = {
Patron::HostResolutionError => "Error resolving remote host.",
...
}

response = catch_exceptions(exceptions, :exit_code => 1) { session.get(url) }


It's usually handy to write this kind of wrappers so the main code keeps clean (on the other hand, if it gets messier and convoluted it's a good sign the abstraction is just not working).

• Apparently, catch can only take 0..1 arguments. As I get an error saying so when I try to run this. – Mark Szymanski Apr 23 '11 at 23:03
• @Mark. Sorry, I didn't mean Ruby's catch, this is a custom method. Call it with a different name: catch_exceptions, for example. – tokland Apr 24 '11 at 6:50