fix(local): Point trace view --web at the trace detail route - #1314
Conversation
`buildTraceUrl` emitted `/traces/{traceId}/`, which matches no route. The
trace detail view is mounted at `trace/:traceSlug/` under both `traces/` and
`explore/traces/`, so the `trace/` segment is what distinguishes a detail URL
from the traces list. Without it Sentry falls back to the list and drops the
trace ID, so `sentry trace view --web <id>` never opened the trace.
Switch to the canonical `/explore/traces/trace/{traceId}/`, matching the
`explore/` namespace `buildLogsUrl` and `buildReplayUrl` already use.
`parseSentryUrl` gains `matchTracePath`, mirroring `matchReplayPath`: it
accepts the canonical path and still parses legacy `traces/{id}/` links so
previously-copied URLs keep resolving.
Affects `trace view --web`, `trace logs --web`, and the `Link` row in
`formatLogDetails`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Codecov Results 📊✅ Patch coverage is 96.15%. Project has 5485 uncovered lines. Files with missing lines (1)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 81.76% 81.77% +0.01%
==========================================
Files 430 430 —
Lines 30063 30083 +20
Branches 19707 19719 +12
==========================================
+ Hits 24578 24598 +20
- Misses 5485 5485 —
- Partials 2043 2043 —Generated by Codecov Action |
There was a problem hiding this comment.
traced through this — the fix is correct. `explore/traces/trace/{id}` matches the sibling builders (`explore/logs/`, `explore/replays/{id}/`) already in this file, and the missing `trace/` segment is exactly why the ID was getting dropped onto the list route.
`matchTracePath` handles all three shapes cleanly (canonical, traces/trace/{id}, and legacy traces/{id}), and its ordering ahead of matchReplayPath is safe since it returns absent for anything that isn't traces. Legacy parse cases are retained, so previously-copied links keep resolving. verified the affected tests pass locally (the 2 applySentryUrlContext failures are pre-existing on main and unrelated).
one non-blocking nit: the parser file's top-level JSDoc (the "Recognizes these path patterns" list around lines 291/300) still only mentions the legacy traces/{traceId}/ form — worth adding the new canonical explore/traces/trace/{traceId}/ there for completeness. not a blocker.
|
Jared,
Push a commit fixing this please. Also, check the PR against |
|
Done — pushed e799547 adding the canonical Checked against Thanks @sergical for the fix! |
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 e799547. Configure here.
Bugbot: matchTracePath treated any segment after explore/traces/ as a
trace ID even without the trace/ segment, so explore/traces/{slug}/
yielded a bogus traceId. Only the legacy non-explore traces/{id}/ form
should match without trace/; require it under explore/.
Seer: matchSubdomainPath handled matchReplayPath's list status (org-only) but not the equivalent trace list status, so a bare subdomain trace list URL (explore/traces/) returned null. Mirror the replay handling.

What was broken
Three commands printed or opened links that don't work:
sentry trace view --web <trace-id>— opens the traces list instead of the trace you asked forsentry trace logs --web <trace-id>— samesentry log view <log-id>— theLinkrow it prints is a dead linkIn every case you end up on a list page with your trace ID silently dropped.
Why
We build the URL as:
That path doesn't exist. In Sentry's router the trace page lives at
trace/:traceSlug/, mounted under bothtraces/andexplore/traces/. So the real URL needs atrace/segment in the middle:Without it the URL matches the list route instead, and the ID is thrown away. That's why you land on the list.
This is just old code. The other builders in the same file were already moved to the new
explore/paths (buildLogsUrl→/explore/logs/,buildReplayUrl→/explore/replays/{id}/). Traces got missed.The fix
trace/segment and theexplore/prefix.traces/{id}/shape too, so links people already copied keep working.Tests updated for the new URL, plus cases covering the old one so the fallback stays working.
🤖 Generated with Claude Code