This is a fun little exception in Ruby that you have to catch explicitly in order to get hold of it in a rescue block.

Say you had the following:

1
2
3
4
5
6
7
require 'net/pop3'
begin
  Net::POP3.auth_only(@server, @port, @username, @password)
rescue => e
  write_error_to_logfile(e)
  do_something_sensible
end

And the mail server could not be reached due to transient network problems -> that is, you are getting a socket timeout error.

Well, your code in the rescue block won’t get executed! Even though the script raises an Error!

Why is this?

Simple answer, because Timeout::Error is not a subclass of StandardError, it is a subclass of the Interrupt class.

So, that means you have to catch it explicitly, like so:

1
2
3
4
5
6
7
8
9
10
require 'net/pop3'
begin
  Net::POP3.auth_only(@server, @port, @username, @password)
rescue => e
  write_error_to_logfile(e)
  do_something_sensible
rescue Timeout::Error => e
  write_error_to_logfile(e)
  do_something_sensible_for_timeout
end

And all will be good again, error caught!

blogLater

Mikel