Why you're getting this issue
This is a double-check request, not a confirmed bug report — feel free to close it if it doesn't apply here.
We hit a bug in the Sentry Cocoa SDK that caused an incident: the SDK read the rate-limit HTTP response headers X-Sentry-Rate-Limits and Retry-After case-sensitively. Because HTTP/2 (RFC 9113 §8.2.1) and HTTP/3 (RFC 9114 §4.2) send header field names lowercased on the wire, the lookup missed the header and the SDK fell back to rate-limiting all data categories — silently over-dropping telemetry when only one category was actually rate-limited.
As part of that action item we audited every SDK for the same pattern (using Claude Code, see below). This SDK was flagged as potentially affected. Please double-check the finding below.
What the audit flagged
The transport matches the two headers with exact, case-sensitive keys via :proplists.get_value/3:
The default HTTP client is Finch/Mint (lib/sentry/config.ex#L623 — default: Sentry.FinchClient), and Mint lowercases response header names, so the exact-match lookup against the mixed-case literals appears to miss. On a 429 that leads to a global all-category rate limit:
Worth noting while verifying: a test comment already documents this behaviour, but the categorized-limit tests pin the legacy Hackney client instead of fixing production —
test/sentry/telemetry_processor_integration_test.exs#L314-L315:
# Use HackneyClient because FinchClient (Mint) lowercases response headers,
# which prevents the transport from matching "X-Sentry-Rate-Limits".
If confirmed
Look both headers up case-insensitively, and add a test that runs under the default Finch client with a lowercased x-sentry-rate-limits:
defp get_header(headers, name) do
down = String.downcase(name)
Enum.find_value(headers, fn {k, v} ->
if String.downcase(k) == down, do: v
end)
end
This issue was generated with Claude Code while auditing all SDKs for incident INC-2357. It is a flag to be verified, not a confirmed defect. Cited lines were checked against source at commit b871a947.
How to double-check this yourself with Claude Code
This is the audit we ran. It checks whether an SDK reads X-Sentry-Rate-Limits / Retry-After case-insensitively.
1. Clone the repo and open Claude Code in it:
git clone --depth 1 https://github.com/getsentry/sentry-elixir
cd sentry-elixir
claude
2. Give Claude Code this prompt:
Audit how this SDK reads the HTTP response headers X-Sentry-Rate-Limits and Retry-After (these two only). The bug we are hunting: HTTP/2 (RFC 9113 §8.2.1) and HTTP/3 (RFC 9114 §4.2) lowercase header field names on the wire, so a case-sensitive lookup can miss the header. When X-Sentry-Rate-Limits is missed on a 429, many SDKs fall back to rate-limiting all categories, silently over-dropping all telemetry.
Do not judge by the string casing alone — identify the default HTTP client and how it delivers header-name casing, then trace the lookup to the matching code and determine whether it is genuinely case-sensitive. Use these lenses: (1) follow the response header names forward from the wire to the match, noting any normalization; (2) treat it as guilty until you can prove the lookup is case-insensitive under the default client; (3) check whether the rate-limit tests ever feed a lowercased header name under the default client; (4) grep comments/CHANGELOG for prior awareness. Report a verdict of confirmed-bug / fragile / safe with exact file:line evidence, and whether a missed header degrades to an all-category (global) rate limit.
3. (Optional) higher confidence: ask Claude Code to run the audit a second time "with a different method and without looking at the first result," then diff the two verdicts.
Reference (the correct, case-insensitive implementation): getsentry/sentry-cocoa#8324
Why you're getting this issue
This is a double-check request, not a confirmed bug report — feel free to close it if it doesn't apply here.
We hit a bug in the Sentry Cocoa SDK that caused an incident: the SDK read the rate-limit HTTP response headers
X-Sentry-Rate-LimitsandRetry-Aftercase-sensitively. Because HTTP/2 (RFC 9113 §8.2.1) and HTTP/3 (RFC 9114 §4.2) send header field names lowercased on the wire, the lookup missed the header and the SDK fell back to rate-limiting all data categories — silently over-dropping telemetry when only one category was actually rate-limited.As part of that action item we audited every SDK for the same pattern (using Claude Code, see below). This SDK was flagged as potentially affected. Please double-check the finding below.
What the audit flagged
The transport matches the two headers with exact, case-sensitive keys via
:proplists.get_value/3:lib/sentry/transport.ex#L139—:proplists.get_value("X-Sentry-Rate-Limits", headers, nil)lib/sentry/transport.ex#L157—:proplists.get_value("Retry-After", headers, nil)The default HTTP client is Finch/Mint (
lib/sentry/config.ex#L623—default: Sentry.FinchClient), and Mint lowercases response header names, so the exact-match lookup against the mixed-case literals appears to miss. On a429that leads to a global all-category rate limit:lib/sentry/transport.ex#L146-L149—status == 429 ->RateLimiter.update_global_rate_limit(delay_seconds)Worth noting while verifying: a test comment already documents this behaviour, but the categorized-limit tests pin the legacy Hackney client instead of fixing production —
test/sentry/telemetry_processor_integration_test.exs#L314-L315:If confirmed
Look both headers up case-insensitively, and add a test that runs under the default Finch client with a lowercased
x-sentry-rate-limits:How to double-check this yourself with Claude Code
This is the audit we ran. It checks whether an SDK reads
X-Sentry-Rate-Limits/Retry-Aftercase-insensitively.1. Clone the repo and open Claude Code in it:
git clone --depth 1 https://github.com/getsentry/sentry-elixir cd sentry-elixir claude2. Give Claude Code this prompt:
3. (Optional) higher confidence: ask Claude Code to run the audit a second time "with a different method and without looking at the first result," then diff the two verdicts.
Reference (the correct, case-insensitive implementation): getsentry/sentry-cocoa#8324