Append child exception information in wrapping exceptions

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the exceptions category.

Last Updated: 2024-12-03

I had some code that threw exceptions like

raise ReportRowError, "Cannot have a zero amount"
raise ReportRowError, "Cannot have a negative amount"
raise ReportRowError, "Cannot have fee larger than gross"

Then higher up the stack, I appended contextual information for debugging by rescuing the error and re-raising it:

rescue GenerateFinancialTransactionsReportService::ReportRow::ReportRowError => e
  raise e.class, "Raw transaction #{raw_transaction}."
end

When I ran this code and got an exception, it gave output like

ReportRowError "Raw transaction {date: ..., amount: ...}."

This was problematic though, because I had no idea why the original ReportRowError was thrown in the first case (i.e. the message, "Cannot have a zero amount" was lost)

The fix was to preserve the exception message by appending it to the wrapping exception's message

rescue GenerateFinancialTransactionsReportService::ReportRow::ReportRowError => e
  raise e.class, "Raw transaction #{raw_transaction}. Original error: #{e.messsage}"
end