All lessons

Spot the Tax · Card 12 of 20

Rescue only what you can recover from

Why a generic rescue => e hides every bug, including the ones you wrote last week.

The code

What will this cost you in six months?

def sync_user(user)
  begin
    ExternalApi.update(user.id, user.attributes)
  rescue => e
    Rails.logger.error "Sync failed for user #{user.id}: #{e.message}"
  end
end

The problem

A bare rescue => e catches every StandardError. Network timeouts, JSON parse errors, typos in your code, missing methods, renamed parameters — they all hit the same log line and the method silently returns nil. The call site can't tell anything went wrong, the UI happily reports success, and the audit log says "synced". Six weeks later somebody notices that 4% of users haven't been synced since the last deploy, and the only trace is grep-able lines in production logs that nobody reads.

Take a moment. Before revealing, ask yourself: which exceptions can this code actually do something useful about? Everything else should probably propagate.