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, }