Skip to content

Commit f55826d

Browse files
cvxluoclaude
andauthored
fix(api): Preserve RateLimitExceeded metadata in handle_query_errors (#109821)
Re-raise RateLimitExceeded instead of converting to Throttled in handle_query_errors(), so `custom_exception_handler` can capture the rate limit metadata (policy, quota_unit, storage_key, quota_used, rejection_threshold) onto the request for access log middleware. No changes for the user, since `custom_exception_handler` will still reraise `Throttled` with the same error message for the frontend. Co-authored-by: Claude <noreply@anthropic.com>
1 parent ea5a376 commit f55826d

File tree

4 files changed

+5
-10
lines changed

4 files changed

+5
-10
lines changed

src/sentry/api/handlers.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from rest_framework.exceptions import Throttled
33
from rest_framework.views import exception_handler
44

5+
from sentry.search.events.constants import RATE_LIMIT_ERROR_MESSAGE
56
from sentry.types.ratelimit import SnubaRateLimitMeta
67
from sentry.utils.snuba import RateLimitExceeded
78

@@ -30,9 +31,7 @@ def custom_exception_handler(exc, context):
3031
level="warning",
3132
)
3233
# let the client know that they've been rate limited with details
33-
exc = Throttled(
34-
detail="Rate limit exceeded. Please try your query with a smaller date range or fewer projects."
35-
)
34+
exc = Throttled(detail=RATE_LIMIT_ERROR_MESSAGE)
3635

3736
response = exception_handler(exc, context)
3837

src/sentry/api/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ def handle_query_errors() -> Generator[None]:
416416
arg = error.args[0] if len(error.args) > 0 else None
417417
if isinstance(error, RateLimitExceeded):
418418
sentry_sdk.set_tag("query.error_reason", "RateLimitExceeded")
419-
raise Throttled(detail=RATE_LIMIT_ERROR_MESSAGE)
419+
raise
420420
if isinstance(
421421
error,
422422
(

tests/sentry/api/test_handlers.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from rest_framework.permissions import AllowAny
44

55
from sentry.api.base import Endpoint
6+
from sentry.search.events.constants import RATE_LIMIT_ERROR_MESSAGE
67
from sentry.testutils.cases import APITestCase
78
from sentry.testutils.silo import control_silo_test
89
from sentry.utils.snuba import RateLimitExceeded
@@ -30,7 +31,4 @@ def test_simple(self) -> None:
3031
resp = self.get_response()
3132
assert resp.status_code == 429
3233

33-
assert (
34-
resp.data["detail"]
35-
== "Rate limit exceeded. Please try your query with a smaller date range or fewer projects."
36-
)
34+
assert resp.data["detail"] == RATE_LIMIT_ERROR_MESSAGE

tests/sentry/api/test_utils.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
QueryOutsideRetentionError,
3030
QuerySizeExceeded,
3131
QueryTooManySimultaneous,
32-
RateLimitExceeded,
3332
SchemaValidationError,
3433
SnubaError,
3534
UnqualifiedQueryError,
@@ -185,7 +184,6 @@ def test_handle_query_errors(self, mock_parse_error: MagicMock) -> None:
185184
QueryOutsideRetentionError,
186185
QuerySizeExceeded,
187186
QueryTooManySimultaneous,
188-
RateLimitExceeded,
189187
SchemaValidationError,
190188
SnubaError,
191189
UnqualifiedQueryError,

0 commit comments

Comments
 (0)