Client Reports

SDK self-reporting protocol for tracking discarded events and their discard reasons.

Statusstable
Version1.21.0(changelog)

Client reports are a protocol feature that let SDKs send status reports about themselves to Sentry. They are primarily used to emit outcomes for events that were never sent — providing visibility into what is happening on the SDK side that affects the user experience.

Not to be confused with User Feedback.

Due to a bug in Relay which discards envelopes containing unknown envelope items, the minimum required Sentry version for client reports is 21.9.0.

Related specs:


An outcome describes the fate of a telemetry item — whether it was accepted, filtered, rate-limited, or discarded. Client reports cover the discarded category: items that were never sent to Sentry.

A discard reason is a string that explains why a telemetry item was dropped. Each discarded item is categorized by reason and data category.

Data categories (e.g., error, transaction, span) identify the type of telemetry item that was discarded. These are the same categories used for rate limits.


Stablespecified since 1.0.0

Client reports are sent as envelope items to Sentry, typically as separate envelopes or with one of the already scheduled envelopes. Their main purpose is to bring visibility into what is happening on the SDK side.

SDKs might drop events in several places — transport queue overflow, rate limit backoff, sampling, before_send, event processors — and this loss can be invisible to a customer. Client reports let an SDK emit such event outcomes to provide data about how often this is happening.

The party that drops an envelope item MUST record and report it.

SDKs can assume client reports are never rate limited (since 1.9.0). The server minimizes the possibility of client reports getting rate limited, but the SDKs shouldn't worry about this edge case as this feature is best-effort.

Bugs in SDKs are out of scope for client reports and are not tracked using client reports (since 1.7.0).

Client reports do not expect 100 percent correct numbers, and it is acceptable for SDKs to lose a small number of client reports. The expectation is to give users an approximation of specific outcomes.

Stablespecified since 1.8.0

When SDKs receive an HTTP 2xx status code response from Sentry, they MUST consider it a successful send. No client report is recorded.

Stablespecified since 1.8.0

If Sentry returns an HTTP 4xx or HTTP 5xx status code, SDKs:

  • MUST discard the envelope.
  • MUST record a client report with the discard reason send_error. For HTTP 429 and HTTP 413, follow the dedicated sections below instead, as they have additional requirements.
Stablespecified since 1.19.0

For an HTTP 413 Content Too Large response, SDKs:

  • MUST discard the envelope and record a client report with the discard reason send_error. Upstream usually records a client report for oversized envelopes, but not always. Double-counting is preferable to not counting, so users are aware of all dropped envelopes. Since client reports are not expected to be fully accurate, we accept this tradeoff for now.
  • MUST NOT retry sending the envelope.
  • SHOULD log an error, informing users that the envelope was discarded due to size limits.
  • MAY add information from the response body to the logged error. If doing so, SDKs MUST be aware that Relay can change or remove information in the response body for an HTTP 413 at any time without notice.
Stablespecified since 1.3.0

For an HTTP 429 Too Many Requests response, SDKs:

  • MUST respect the rate limiting rules, such as correctly parsing the retry-header.
  • MUST discard the envelope, but MUST NOT record a client report, because the upstream already does this. Doing this would double-count client reports for discarded envelopes.
  • MUST NOT retry sending the envelope.
Stablespecified since 1.11.0

When failures occur that are caused by processing in the SDK itself, SDKs MUST discard the envelope and record a client report with the discard reason internal_sdk_error.

Stablespecified since 1.8.0

SDKs MAY retry sending the envelope when a network error occurs (connection timeout, DNS resolution failure, connection reset by peer). No client report is required for retried network errors.

Stablespecified since 1.14.0

When a transaction is dropped, SDKs MUST record an additional span category entry containing the number of spans inside the transaction plus one. The plus one stems from the fact that Relay extracts an additional span from the transaction. If a transaction contains no spans, SDKs still report one dropped transaction and one dropped span. This also applies to transactions that are not sampled.

If certain spans are dropped in beforeSendTransaction, an event processor, etc., SDKs also report those.

Stablespecified since 1.21.0

When a log is dropped, SDKs MUST record an additional log_byte category entry containing the byte size of the log. This provides visibility into the volume of log data being discarded, complementing the item count reported under the log_item category.

Since client reports use a (reason, category) → quantity map for aggregation, byte sizes are tracked as a separate category rather than an extra field. Each dropped log produces two entries in the map: one incrementing the log_item count by 1, and one incrementing the log_byte count by the log's byte size.

The byte size does not need to be exact. SDKs MAY use an approximation, such as the in-memory size of the log object or the size of its serialized representation. The goal is to provide a useful signal, not a precise measurement.

Candidatespecified since 1.20.0

SDKs SHOULD use a single, centralized ClientReports component per client that handles aggregation internally:

  • MUST be scoped per client — if an SDK supports multiple client instances, each MUST have its own ClientReports instance. This is required because clients are already scoped per DSN, so scoping ClientReports per client ensures report data is attributed to the correct DSN and avoids mixing data across instances.
  • SHOULD be accessible throughout the SDK, so any component that drops telemetry can record into it.
  • SHOULD use a no-op implementation when client reports are disabled via the sendClientReports option, to avoid overhead.
  • SHOULD maintain a map where the key is a reason-category string and the value is the number of dropped items. Components call a Record method to increment counters directly.
  • MUST be thread safe for concurrent read and write access, since multiple SDK components record into it simultaneously.
  • MUST atomically read and reset all counters during extraction to prevent double-counting.
Candidatespecified since 1.20.0

The original specification suggested tracking client reports directly within the transport. However, due to the increase in telemetry data types and the possibility of data loss at various stages in the SDK, this approach no longer scales well. Client reports must be accessible across different parts of the SDK. Thus, we now recommend developing a separate ClientReports component rather than integrating it into the transport.

SDKs SHOULD own the ClientReports component at the client level, regardless of whether they implement the full telemetry processor architecture. This keeps the transport focused on delivery.

Once SDKs implement the telemetry processor, the client SHOULD NOT forward reports to the transport directly. Instead, the telemetry processor SHOULD be responsible for extracting the aggregated report and attaching it to outgoing envelopes or sending it as a standalone envelope.

Client reports are separate from the normal telemetry data flow — they do not go through buffers or queues. See the telemetry processor client reports section for the full architecture diagram and recording points.

Stablespecified since 1.4.0

It is not required, for example:

  • to persist the data when an application crashes.
  • to move an envelope item with a client report to the next envelope when the cache for envelopes is full.

SDKs SHOULD minimize unnecessary HTTP requests and MUST NOT send an envelope for each discarded event. Adjust these recommendations as needed:

  1. For low-frequency apps (mobile/web): Attach discarded events to scheduled envelopes. Fewer client reports are acceptable in such cases.
  2. For high-frequency apps (backends): Periodically flush discarded events or attach to scheduled envelopes.
Stablespecified since 1.5.0

SDKs SHOULD provide a way to turn sending of client reports on and off. This option is called send_client_reports or sendClientReports.

Stablespecified since 1.4.0

For SDKs still sending legacy events instead of envelopes for backward compatibility with older Sentry servers, the recommendation is to send the client report as a separate envelope or attach it to pending session envelopes.

Stablespecified since 1.4.0

There is no expectation that such bookkeeping can work transparently for custom transports. Consequently, it's acceptable if client reports are optional for custom transports.


Stablespecified since 1.0.0

Item type "client_report" contains a client report payload encoded in JSON.

Constraints:

  • This Item MAY occur multiple times per Envelope, but SDKs SHOULD avoid sending more client reports than necessary.
  • This Item can either be included in an Envelope with other Items, or it MAY be sent by itself.
  • No envelope headers are required.
  • Size limit: 4 KiB (see Envelopes — Size Limits).
Stablespecified since 1.0.0

A client report consists of a JSON payload with the following fields:

FieldTypeRequiredSinceDescription
timestampString or NumberOPTIONAL1.0.0The timestamp of when the client report was created. Must be an ISO DateTime string or a UNIX timestamp. If not sent, the server assumes the current UTC timestamp. In the data model, this is called received.
discarded_eventsArrayREQUIRED1.0.0List of outcome objects {reason, category, quantity}.

Each outcome object in discarded_events has:

FieldTypeRequiredDescription
reasonStringREQUIREDA discard reason that defines why events were lost (see Discard Reasons).
categoryStringREQUIREDThe data category for which the discard reason applies (since 1.2.0).
quantityNumberREQUIREDThe number of events which were lost.
Stablespecified since 1.0.0

The following discard reasons are defined for discarded_events:

ReasonSinceDescription
queue_overflow1.0.0SDK internal queue (e.g., transport queue) overflowed.
cache_overflow1.0.0SDK internal cache (e.g., offline event cache) overflowed.
ratelimit_backoff1.0.0Rate limit instructed the SDK to back off.
network_error1.0.0Network errors, not retried.
sample_rate1.0.0Configured sample rate.
before_send1.0.0Dropped in before_send.
event_processor1.0.0Dropped by event processor; may also be used for ignored exceptions/errors (since 1.6.0).
send_error1.11.0Error when sending (e.g., 400 response).
internal_sdk_error1.11.0Internal SDK error (e.g., web worker crash).
insufficient_data1.12.0Lack of data in the event (e.g., not enough samples in a profile).
backpressure1.13.0Downsampling due to system load.
buffer_overflow1.15.0SDK internal buffer (e.g., breadcrumbs buffer) overflowed.
ignored1.16.0Telemetry item was ignored by the SDK (e.g., a span was ignored by ignore_spans; can also be used by other deny-list mechanisms).
invalid1.17.0Failed validation (e.g., replay session exceeded maximum allowed length).

In case a reason needs to be added, it also has to be added to the allowlist in snuba.

Stablespecified since 1.1.0

The following outcome types are reserved for relay use:

rate_limited_events, filtered_events, filtered_sampling_events

These function like discarded_events (same {reason, category, quantity} structure) but identify events that were rate limited, filtered, or filtered by dynamic sampling at a relay. Client SDKs MUST NOT emit these unless they are operating as a relay. The reason codes for these need to match the reason codes that relay would emit directly to Sentry.


Copied
{  "timestamp": "2020-02-07T14:16:00Z",  "discarded_events": [  {  "reason": "queue_overflow",  "category": "error",  "quantity": 23  },  {  "reason": "queue_overflow",  "category": "transaction",  "quantity": 1321  }  ] } 

Copied
{} {"type":"client_report"} {"timestamp":"2020-02-07T14:16:00Z","discarded_events":[{"reason":"queue_overflow","category":"error","quantity":23}]} 

When a transaction with 2 spans is dropped due to queue overflow:

Copied
{  "discarded_events": [  {  "reason": "queue_overflow",  "category": "transaction",  "quantity": 1  },  {  "reason": "queue_overflow",  "category": "span",  "quantity": 3  }  ] } 

The span quantity is 3 (2 spans + 1 for the transaction itself, since Relay extracts an additional span from the transaction).

When 5 logs totaling approximately 12,400 bytes are dropped due to buffer overflow:

Copied
{  "discarded_events": [  {  "reason": "buffer_overflow",  "category": "log_item",  "quantity": 5  },  {  "reason": "buffer_overflow",  "category": "log_byte",  "quantity": 12400  }  ] } 

The log_item entry counts the number of dropped logs, while the log_byte entry tracks the total byte size of those logs.


VersionDateSummary
1.21.02026-03-06Added log byte outcomes for tracking discarded log data size
1.20.02026-03-04Added architecture guidance
1.19.02026-02-06Added network failure recording rules (send_error for 4xx/5xx, no report for 429)
1.18.02026-01-29Added telemetry processor integration, updated SDK recommendations
1.17.02026-01-21Added `invalid` discard reason
1.16.02026-01-14Added `ignored` discard reason
1.15.02025-01-21Added `buffer_overflow` discard reason
1.14.02024-09-10Added span outcome tracking (span category for dropped transactions)
1.13.02023-12-12Added `backpressure` discard reason
1.12.02023-06-26Added `insufficient_data` discard reason
1.11.02023-02-09Added `send_error` and `internal_sdk_error` discard reasons
1.10.02022-06-23Added product context (Scope and Intent)
1.9.02022-05-06Client reports never rate limited by server
1.8.02022-04-11Added HTTP status code handling guidance
1.7.02022-04-06SDK bugs out of scope for client reports
1.6.02022-04-04event_processor discard for ignored exceptions
1.5.02022-04-04Added `send_client_reports` configuration option
1.4.02022-03-28SDK recommendations, legacy events, custom transports sections
1.3.02022-03-28No double counting — MUST NOT record for HTTP 429
1.2.02022-03-22Specified data categories for discard reasons
1.1.02021-12-24Relay outcome types (rate_limited_events, filtered_events, filtered_sampling_events)
1.0.12021-09-10Fixed field name from discard_reason to reason
1.0.02021-09-10Initial spec — client report protocol, envelope format, discard reasons
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").