From 6bca764fff0b3d9ec7c82f7eee550c9dc16c1fa0 Mon Sep 17 00:00:00 2001 From: Charlie Luo Date: Mon, 2 Mar 2026 10:32:16 -0800 Subject: [PATCH] feat(snuba): handle TOO_MANY_BYTES as clickhouse error instead of rate limit Add QueryBytesScannedExceeded exception for ClickHouse error code 307 (TOO_MANY_BYTES). This is raised when a query exceeds the max_bytes_to_read limit set by an allocation policy, distinct from Snuba-level rate limiting. - Add QueryBytesScannedExceeded to clickhouse_error_codes_map (code 307) - Handle it explicitly in handle_query_errors() before the generic QueryExecutionError catch, returning a descriptive error message Co-authored-by: Claude --- src/sentry/api/utils.py | 6 ++++++ src/sentry/utils/snuba.py | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/sentry/api/utils.py b/src/sentry/api/utils.py index 3b4e4045e47a8c..16c102179cadc8 100644 --- a/src/sentry/api/utils.py +++ b/src/sentry/api/utils.py @@ -49,6 +49,7 @@ from sentry.utils.sdk import capture_exception, merge_context_into_scope, set_span_attribute from sentry.utils.snuba import ( DatasetSelectionError, + QueryBytesScannedExceeded, QueryConnectionFailed, QueryExecutionError, QueryExecutionTimeMaximum, @@ -402,6 +403,11 @@ def handle_query_errors() -> Generator[None]: if isinstance(error, RateLimitExceeded): sentry_sdk.set_tag("query.error_reason", "RateLimitExceeded") raise Throttled(detail=RATE_LIMIT_ERROR_MESSAGE) + elif isinstance(error, QueryBytesScannedExceeded): + sentry_sdk.set_tag("query.error_reason", "QueryBytesScannedExceeded") + raise TimeoutException( + detail="Query has exceeded its bytes scanned limit. Please try your query with a smaller date range or fewer projects." + ) if isinstance( error, ( diff --git a/src/sentry/utils/snuba.py b/src/sentry/utils/snuba.py index e88baf3c044e18..c6df552ebc91f8 100644 --- a/src/sentry/utils/snuba.py +++ b/src/sentry/utils/snuba.py @@ -446,6 +446,14 @@ class QueryConnectionFailed(QueryExecutionError): """ +class QueryBytesScannedExceeded(QueryExecutionError): + """ + The query exceeded the max_bytes_to_read limit set by an allocation policy. + This is a ClickHouse-level rejection (error code 307, TOO_MANY_BYTES), + distinct from Snuba-level rate limiting. + """ + + clickhouse_error_codes_map = { 10: QueryMissingColumn, 43: QueryIllegalTypeOfArgument, @@ -456,6 +464,7 @@ class QueryConnectionFailed(QueryExecutionError): 241: QueryMemoryLimitExceeded, 271: DatasetSelectionError, 279: QueryConnectionFailed, + 307: QueryBytesScannedExceeded, }