Introduction
This plan's goal is to propose a general guideline on how to handle exceptions that occur when the SDK is sending events to Sentry.
The goal is to make sure:
- Applications won't be interrupted unnecessarily.
- Users can know if the event is sent or not.
Related Issues
Below are the types of exceptions that could occur when sending an event to Sentry:
External Exceptions
An external exception is an error triggered by something outside of the SDK's control. For example:
- Networking error
- Redis connection error (fail to enqueue a background job)
These exceptions shouldn't interrupt the user's program. For example, failing to send a transaction to Sentry can't cause the response to return 500. This means:
- these exceptions should be rescued whenever possible.
- however, if these exceptions happen in a separated process, like a background job, they could fail for triggering a retry.
- whatever happens needs to be written in the log.
User Exceptions
Because the SDK also invokes user-defined callbacks, like before_send, those callbacks could trigger arbitrary errors. For example:
These exceptions should not be swallowed.
Exception Handling Principles
- Any exception happens after
Sentry.capture_* is called shouldn't crash the user's app.
- Any exception happens in the background should be raised.
Exception Hotspots in Ruby SDK's Event Sending Flow
Client#capture_event <- should rescue and log all the errors
async block - could be either user or external exception
Client#send_event
before_send callback - user exception
HTTPTransport#send_data - external exception
As you can see, the flow can trigger either user or external exceptions, which makes handling them a bit tricky.
Exception Handling In Different Scenarios
Now, because Ruby SDK has different sync/async options, the situation gets even more complicated. Here's the breakdown for different scenarios:
Sending Events Inline (without async nor background worker)
Client#capture_event <- should rescue and log all the errors
Client#send_event
before_send callback - user exception
HTTPTransport#send_data - external exception
With Async
These happen inline
Client#capture_event <- should rescue and log all the errors
async block - could be either user or external exception
These happen in the worker
Client#send_event <- should raise both external and user exception
before_send callback - user exception
HTTPTransport#send_data - external exception
With Background Worker
These happen inline
These happen in the worker
Client#send_event <- should raise both external and user exception
before_send callback - user exception
HTTPTransport#send_data - external exception
Diagram

Introduction
This plan's goal is to propose a general guideline on how to handle exceptions that occur when the SDK is sending events to Sentry.
The goal is to make sure:
Related Issues
before_sendcallback #1289Below are the types of exceptions that could occur when sending an event to Sentry:
External Exceptions
An external exception is an error triggered by something outside of the SDK's control. For example:
These exceptions shouldn't interrupt the user's program. For example, failing to send a transaction to Sentry can't cause the response to return 500. This means:
User Exceptions
Because the SDK also invokes user-defined callbacks, like
before_send, those callbacks could trigger arbitrary errors. For example:These exceptions should not be swallowed.
Exception Handling Principles
Sentry.capture_*is called shouldn't crash the user's app.Exception Hotspots in Ruby SDK's Event Sending Flow
Client#capture_event<- should rescue and log all the errorsasyncblock - could be either user or external exceptionClient#send_eventbefore_sendcallback - user exceptionHTTPTransport#send_data- external exceptionAs you can see, the flow can trigger either user or external exceptions, which makes handling them a bit tricky.
Exception Handling In Different Scenarios
Now, because Ruby SDK has different sync/async options, the situation gets even more complicated. Here's the breakdown for different scenarios:
Sending Events Inline (without async nor background worker)
Client#capture_event<- should rescue and log all the errorsClient#send_eventbefore_sendcallback - user exceptionHTTPTransport#send_data- external exceptionWith Async
These happen inline
Client#capture_event<- should rescue and log all the errorsasyncblock - could be either user or external exceptionThese happen in the worker
Client#send_event<- should raise both external and user exceptionbefore_sendcallback - user exceptionHTTPTransport#send_data- external exceptionWith Background Worker
These happen inline
Client#capture_eventThese happen in the worker
Client#send_event<- should raise both external and user exceptionbefore_sendcallback - user exceptionHTTPTransport#send_data- external exceptionDiagram