fix: Rate Limiting All Categories on Lowercased Header#8324
Merged
Conversation
Over HTTP/2 header field names arrive lowercased and recent Apple OS versions no longer canonicalize custom header names. The case-sensitive allHeaderFields lookup for X-Sentry-Rate-Limits then missed, so a category-scoped 429 was treated as a rate limit for all categories. Read X-Sentry-Rate-Limits and Retry-After case-insensitively via value(forHTTPHeaderField:), with a case-sensitive fallback for the macOS 10.14 deployment target.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📲 Install BuildsiOS
|
Contributor
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 1155f0c | 1222.41 ms | 1251.18 ms | 28.76 ms |
| dff20e3 | 1225.19 ms | 1258.66 ms | 33.47 ms |
| 05bac3b | 1220.16 ms | 1255.81 ms | 35.65 ms |
| 79001eb | 1226.09 ms | 1258.79 ms | 32.70 ms |
| 66415de | 1221.21 ms | 1253.28 ms | 32.07 ms |
| 2fe9650 | 1228.33 ms | 1260.78 ms | 32.46 ms |
| b6fa517 | 1218.83 ms | 1257.47 ms | 38.63 ms |
| 089f6f4 | 1219.37 ms | 1253.95 ms | 34.58 ms |
| 89aaba2 | 1239.60 ms | 1264.67 ms | 25.08 ms |
| 59213ba | 1223.66 ms | 1258.02 ms | 34.36 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 1155f0c | 24.14 KiB | 1.16 MiB | 1.13 MiB |
| dff20e3 | 24.14 KiB | 1.15 MiB | 1.13 MiB |
| 05bac3b | 24.14 KiB | 1.18 MiB | 1.15 MiB |
| 79001eb | 24.14 KiB | 1.19 MiB | 1.16 MiB |
| 66415de | 24.14 KiB | 1.16 MiB | 1.13 MiB |
| 2fe9650 | 24.14 KiB | 1.17 MiB | 1.15 MiB |
| b6fa517 | 24.14 KiB | 1.14 MiB | 1.12 MiB |
| 089f6f4 | 24.14 KiB | 1.18 MiB | 1.15 MiB |
| 89aaba2 | 24.14 KiB | 1.16 MiB | 1.14 MiB |
| 59213ba | 24.14 KiB | 1.22 MiB | 1.20 MiB |
philipphofmann
commented
Jul 3, 2026
philipphofmann
marked this pull request as ready for review
July 3, 2026 07:48
philipphofmann
requested review from
NinjaLikesCheez,
itaybre,
noahsmartin and
philprime
as code owners
July 3, 2026 07:48
itaybre
approved these changes
Jul 3, 2026
itaybre
left a comment
Contributor
There was a problem hiding this comment.
LGTM, please update the changelog when you have the information
philprime
approved these changes
Jul 3, 2026
philprime
left a comment
Member
There was a problem hiding this comment.
LGTM with one comment for you to consider
itaybre
reviewed
Jul 3, 2026
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
philipphofmann
added a commit
that referenced
this pull request
Jul 6, 2026
The SDK rate-limited all categories when receiving a lowercase HTTP X-Sentry-Rate-Limits header, because it looked the header up case-sensitively via allHeaderFields[...], missed it, and fell back to rate limiting all categories when receiving a 429. So the SDK was over-ratelimiting. Now, the SDK retrieves the X-Sentry-Rate-Limits and Retry-After case-insensitively. Backport of #8324 to the v8 branch. The rate-limit code is still Objective-C on v8.x (it was ported to Swift on main), so the fix is reimplemented in SentryDefaultRateLimits.m. It uses -[NSHTTPURLResponse valueForHTTPHeaderField:], which reads headers case-insensitively, on iOS 13 / macOS 10.15 / tvOS 13 / watchOS 6 and above, and falls back to a case-insensitive scan of allHeaderFields on the lower v8 deployment targets (iOS 11 / macOS 10.13) where that API isn't available. Fixes #8322
philipphofmann
added a commit
that referenced
this pull request
Jul 6, 2026
The SDK rate-limited all categories when receiving a lowercase HTTP X-Sentry-Rate-Limits header, because it looked the header up case-sensitively via allHeaderFields[...], missed it, and fell back to rate limiting all categories when receiving a 429. So the SDK was over-ratelimiting. Now, the SDK retrieves the X-Sentry-Rate-Limits and Retry-After case-insensitively. Backport of #8324 to the v8 branch. The rate-limit code is still Objective-C on v8.x (it was ported to Swift on main), so the fix is reimplemented in SentryDefaultRateLimits.m. It uses -[NSHTTPURLResponse valueForHTTPHeaderField:], which reads headers case-insensitively, on iOS 13 / macOS 10.15 / tvOS 13 / watchOS 6 and above, and falls back to a case-insensitive scan of allHeaderFields on the lower v8 deployment targets (iOS 11 / macOS 10.13) where that API isn't available. Fixes #8322
philipphofmann
added a commit
that referenced
this pull request
Jul 6, 2026
The SDK rate-limited all categories when receiving a lowercase HTTP X-Sentry-Rate-Limits header, because it looked the header up case-sensitively via allHeaderFields[...], missed it, and fell back to rate limiting all categories when receiving a 429. So the SDK was over-ratelimiting. Now, the SDK retrieves the X-Sentry-Rate-Limits and Retry-After case-insensitively. Backport of #8324 to the v8 branch. The rate-limit code is still Objective-C on v8.x (it was ported to Swift on main), so the fix is reimplemented in SentryDefaultRateLimits.m. It uses -[NSHTTPURLResponse valueForHTTPHeaderField:], which reads headers case-insensitively, on iOS 13 / macOS 10.15 / tvOS 13 / watchOS 6 and above, and falls back to a case-insensitive scan of allHeaderFields on the lower v8 deployment targets (iOS 11 / macOS 10.13) where that API isn't available. Fixes #8322
This was referenced Jul 9, 2026
This was referenced Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
The SDK rate-limited all categories when receiving a lowercase HTTP
X-Sentry-Rate-Limitsheader, because it didn't retrieve the rate limits header and fell back to rate limiting all categories when receiving a 429. So the SDK was over-ratelimiting. Now, the SDK retrieves theX-Sentry-Rate-LimitsandRetry-Aftercase-insensitively.Since HTTP/2 headers must be lowercased
HTTP/2 — RFC 9113, Section 8.2.1 (Field Validity):
https://www.rfc-editor.org/rfc/rfc9113#section-8.2.1
(i.e. uppercase letters are forbidden in field names → they are lowercase.)
HTTP/3 — RFC 9114, Section 4.2 (HTTP Fields):
https://www.rfc-editor.org/rfc/rfc9114#section-4.2
💡 Motivation and Context
Fixes #8322.
💚 How did you test it?
Unit tests.
📝 Checklist
You have to check all boxes before merging:
sendDefaultPIIis enabled.