fix(issues): Route adjacent-event lookups to Events dataset#114474
Merged
fix(issues): Route adjacent-event lookups to Events dataset#114474
Conversation
e799916 to
6e8a2fe
Compare
Fixes SENTRY-5NPK. See PR description for the explanation.
6e8a2fe to
5c11df9
Compare
scttcper
approved these changes
Apr 30, 2026
3 tasks
cleptric
pushed a commit
that referenced
this pull request
May 5, 2026
Fixes [SENTRY-5NPK](https://sentry.sentry.io/issues/SENTRY-5NPK). Navigating prev/next on an issue events page crashed with `QueryIllegalTypeOfArgument: Argument 0 for function arrayConcat must be an array but it has type String` whenever the search query filtered an `ARRAY_FIELDS` column (`!error.type:[A,B]`, `stack.function:[X]`, etc.). **Why It Started 9 Days Ago** #113234 (Apr 17) wired the issue search query into prev/next event navigation, behind a sentry-org allowlist. #113555 (Apr 21 — the day this issue first fired) flipped that to a boolean option. #114063 (Apr 27) made it the default for everyone. Before this rollout, prev/next ignored the query, so the broken SQL was never generated. The dataset asymmetry below was always there but only mattered once filter conditions started flowing through. **Why Switching to `Events` Is the Right Call (Not as Big as It Reads)** `get_adjacent_event_ids` was the last event-fetch method on the issue events page still using `Dataset.Discover`. The methods that load the *initial* event on the very same page already use `Dataset.Events` for error groups: ```python # src/sentry/models/group.py:260 — get_oldest_or_latest_event / get_recommended_event if group.issue_category == GroupCategory.ERROR: dataset = Dataset.Events else: dataset = Dataset.IssuePlatform ``` So when a user opens an issue, the first event loads through `Events`, and then prev/next was sending the same group's same conditions to `Discover`. Both datasets read from the same underlying ClickHouse `errors` storage; the difference is entity-level column resolution. The `Discover` entity tag-promotes columns like `exception_stacks.type` to `tags.value[indexOf(tags.key, ...)]` (a scalar `String`), which makes the existing `hasAny(arrayConcat(name), array(...))` shape produced by `convert_search_filter_to_snuba_query` blow up. The `Events` entity treats those columns as the native nested arrays they are, and the same SQL parses fine. The original justification for `Discover` was a comment claiming it was needed "to enable getting events across both errors and transactions, which is required when doing pagination in discover." Adjacent-event lookups always run within a single group, which is bounded to one entity, so the cross-entity Discover view isn't needed here. The stale comment is removed. The change is scoped: only the non-transaction, non-occurrence branch of `_get_dataset_for_event` flips. Transactions still go to `Transactions`, occurrences/generic still go to `IssuePlatform`. Only error events change, and they now match what the rest of the page already does. **On Test Coverage** No regression test in this PR. Local devservices Snuba's discover entity treats `exception_stacks.type` as a real nested array column, so the production failure mode (tag-promotion to a scalar) doesn't reproduce here. The existing endpoint tests around prev/next navigation still pass.
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.
Fixes SENTRY-5NPK.
Navigating prev/next on an issue events page crashed with
QueryIllegalTypeOfArgument: Argument 0 for function arrayConcat must be an array but it has type Stringwhenever the search query filtered anARRAY_FIELDScolumn (!error.type:[A,B],stack.function:[X], etc.).Why It Started 9 Days Ago
#113234 (Apr 17) wired the issue search query into prev/next event navigation, behind a sentry-org allowlist. #113555 (Apr 21 — the day this issue first fired) flipped that to a boolean option. #114063 (Apr 27) made it the default for everyone. Before this rollout, prev/next ignored the query, so the broken SQL was never generated. The dataset asymmetry below was always there but only mattered once filter conditions started flowing through.
Why Switching to
EventsIs the Right Call (Not as Big as It Reads)get_adjacent_event_idswas the last event-fetch method on the issue events page still usingDataset.Discover. The methods that load the initial event on the very same page already useDataset.Eventsfor error groups:So when a user opens an issue, the first event loads through
Events, and then prev/next was sending the same group's same conditions toDiscover. Both datasets read from the same underlying ClickHouseerrorsstorage; the difference is entity-level column resolution. TheDiscoverentity tag-promotes columns likeexception_stacks.typetotags.value[indexOf(tags.key, ...)](a scalarString), which makes the existinghasAny(arrayConcat(name), array(...))shape produced byconvert_search_filter_to_snuba_queryblow up. TheEventsentity treats those columns as the native nested arrays they are, and the same SQL parses fine.The original justification for
Discoverwas a comment claiming it was needed "to enable getting events across both errors and transactions, which is required when doing pagination in discover." Adjacent-event lookups always run within a single group, which is bounded to one entity, so the cross-entity Discover view isn't needed here. The stale comment is removed.The change is scoped: only the non-transaction, non-occurrence branch of
_get_dataset_for_eventflips. Transactions still go toTransactions, occurrences/generic still go toIssuePlatform. Only error events change, and they now match what the rest of the page already does.On Test Coverage
No regression test in this PR. Local devservices Snuba's discover entity treats
exception_stacks.typeas a real nested array column, so the production failure mode (tag-promotion to a scalar) doesn't reproduce here. The existing endpoint tests around prev/next navigation still pass.