feat(issue): default to recommended sort on Sentry SaaS#1123
Merged
Conversation
`sentry issue list` now defaults to the server-side `recommended` relevance sort on Sentry SaaS (sentry.io), falling back to `date` on self-hosted instances. `recommended` was added to the issue search API on 2026-04-06 and the backend returns HTTP 400 (`Sort key '...' not supported`) for instances that lack it. Self-hosted therefore keeps `date` as the default; an explicit `--sort recommended` there surfaces the API error as-is. Because Stricli flag defaults are static, the `--sort` flag is now optional and the host-dependent default is resolved at runtime via `defaultIssueSort()` (= `isSaaS() ? "recommended" : "date"`), shadow- resolved at the top of `func()` so all downstream code keeps a concrete `flags.sort`. Notes: - No API-layer change: the @sentry/api SDK type already includes `recommended`. - Multi-project merges can't reproduce the server-only recommended score, so `getComparator` falls back to recency (lastSeen) for the client-side merge. Single-project listings are fully server-sorted.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0a3967f. Configure here.
Cursor Bugbot (high severity): after fetching with sort=recommended, the merged result list was always re-sorted client-side with getComparator(flags.sort). For `recommended` the comparator falls back to lastSeen (the relevance score is not in the payload), so a typical single-project `issue list` had its server-provided recommended ordering silently replaced by a date ordering. Only re-sort when merging results from multiple separately-fetched projects, where a client comparator is genuinely required to interleave them. Single-project and org-all responses are already ordered by the server for the requested sort, so their order is now preserved. Adds a regression test asserting a single-project recommended response keeps the server order even when lastSeen would reorder it.
# Conflicts: # .lore.md
Contributor
|
Contributor
Codecov Results 📊✅ Patch coverage is 100.00%. Project has 5052 uncovered lines. Files with missing lines (1)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 81.24% 81.25% +0.01%
==========================================
Files 388 388 —
Lines 26936 26947 +11
Branches 17493 17508 +15
==========================================
+ Hits 21884 21895 +11
- Misses 5052 5052 —
- Partials 1825 1825 —Generated by Codecov Action |
Addresses self-review (adversarial subagent) findings:
- S1: add an end-to-end guard that, when --sort is omitted, the
host-dependent default actually reaches the API (sort=recommended on
SaaS, sort=date on self-hosted). All prior tests passed sort explicitly,
so a regression dropping the `?? defaultIssueSort()` resolution would
have gone uncaught. Verified the new tests fail when the resolution is
reverted.
- S2: when the API rejects an unsupported sort with 400 "Sort key '<x>'
not supported" (e.g. `--sort recommended` against an older self-hosted
instance), emit a sort-specific hint ("use --sort date") instead of the
generic query/time-range/access suggestions. Extracted the shared
formatting into formatDetailWithSuggestions(); hoisted the matcher regex
to module scope. Added build400Detail unit tests.
- N2: make the "explicit sentry.io URL" default test hermetic by clearing
SENTRY_HOST (getConfiguredSentryUrl prefers it).
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.

Summary
sentry issue listnow defaults to the server-siderecommendedrelevance sort on Sentry SaaS (sentry.io), falling back todateon self-hosted instances.Why SaaS-only
recommendedwas added to the issue search API on 2026-04-06. The backend raisesInvalidSearchQuery→ HTTP 400 (Sort key '...' not supported) for instances that lack the sort strategy (sentry/src/sentry/search/snuba/backend.py). Since the CLI supports self-hosted Sentry, an unconditional default would breakissue liston older instances — so self-hosted keepsdate. If a user explicitly runs--sort recommendedagainst an instance that doesn't support it, the resulting 400 is enriched with a sort-specific hint ("this instance does not support the 'recommended' sort; use--sort date") rather than the generic query/time-range suggestions. Theorganizations:issue-stream-recommended-sortfeature flag is UI-exposure only (api_expose=True); it does not gate the API, so every SaaS org can use it today.Implementation
src/lib/sentry-urls.ts— exported the existing privateisSaaS()(routing/UX helper; JSDoc points toisSaaSTrustOriginfor trust decisions).src/commands/issue/list.tsrecommendedtoSortValue/VALID_SORT_VALUES(soparseSortaccepts it) and theListFlagsunion.defaultIssueSort()=isSaaS() ? "recommended" : "date".--sortis now optional and the host-dependent default is resolved at runtime — shadow-resolved at the top offunc()(newListFlagsInputtype) so all downstream code keeps a concreteflags.sort.getComparatorgains an explicitrecommendedcase.appendIssueFlagsomits--sortwhen it equals the active default (defaultIssueSort()instead of hardcoded"date").isMultiProjectso single-project / org-all responses preserve the server's order (fixes the Cursor Bugbot finding whererecommendedwas clobbered by alastSeenfallback).build400Detail).@sentry/apiSDKIssueSorttype already includesrecommended.Known limitations (documented)
getComparatorfalls back to recency (lastSeen). This is identical to the previousdatedefault, so it's not a regression. Single-project and org-all listings (the common case) are fully server-sorted byrecommended.sort, so on SaaS the default key changesdate→recommendedafter upgrading. Any previously-stored cursor stack is silently orphaned and-c next/-c prevstart fresh — self-healing, not corrupting.Tests
list.test.ts:--sortomitted): asserts the API receivessort: "recommended"on SaaS andsort: "date"on self-hosted — guards the actual feature (verified to fail if the default resolution is reverted).recommendedresults aren't reordered bylastSeen(verified to fail without theisMultiProjectguard).defaultIssueSort(SaaS/self-hosted via env),getComparator("recommended"),parseSort("recommended"),appendIssueFlagsdefault-omission, andbuild400Detailsort-hint cases.list.property.test.ts: explicitrecommendedcomparator case (property generators auto-cover it viaVALID_SORT_VALUES).Verification
tsc --noEmitcleancheck:fragmentspasses