Skip to content
This repository was archived by the owner on Oct 23, 2026. It is now read-only.

fix: three bug fixes — sourcemap JSON.parse crash, log per_page cap, dashboard pagination overshoot - #1118

Closed
cursor[bot] wants to merge 3 commits into
mainfrom
cursor/sentry-cli-bug-fixes-aebb
Closed

cursor[bot] wants to merge 3 commits into
mainfrom
cursor/sentry-cli-bug-fixes-aebb

Conversation

@cursor

@cursor cursor Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Three independent bug fixes discovered via code analysis of the codebase. Each fix is a separate commit.


1. fix(sourcemap): Guard JSON.parse in injectDebugId against malformed .map files

Root cause: JSON.parse(mapContent) in src/lib/sourcemap/debug-id.ts:155 was the only unguarded JSON.parse in the codebase. Malformed .map files crash the sourcemap inject command with an opaque SyntaxError.

Reproduction: Run sentry sourcemap inject on a directory containing a .js file whose companion .map has invalid JSON.

Fix: Wrapped in try/catch that throws a ValidationError with the file path, matching the pattern used in inline-sourcemap.ts and throughout the rest of the codebase.


2. fix(logs): Cap per_page at API_MAX_PER_PAGE in log list APIs

Root cause: Both listLogs() and listTraceLogs() in src/lib/api/logs.ts passed the user's --limit directly as per_page. When limit > 100, the API silently caps at 100, but the caller's hasMore check (logs.length >= flags.limit) evaluates to false, hiding remaining data.

Reproduction: Run sentry log list --limit 200 on a project with >100 logs. Only ~100 are returned and the hint says there are no more.

Fix: Cap both calls with Math.min(limit, API_MAX_PER_PAGE), matching the project convention documented in AGENTS.md: "Never pass a per_page value larger than API_MAX_PER_PAGE to the API."


3. fix(dashboard): Drop nextCursor on pagination overshoot in revisions list

Root cause: In src/commands/dashboard/revisions.ts, when multi-page fetching accumulates more results than flags.limit, the excess is trimmed but the API cursor from the last fetched page is still stored. On -c next, those trimmed items are silently skipped.

Reproduction: Run sentry dashboard revisions <id> --limit N where N causes multi-page overshoot (e.g., --limit 150 with 100 items per page, where 2 pages return 160 items total).

Fix: Drop nextCursor when results overshoot the limit, matching the autoPaginate() pattern in infrastructure.ts (lines 419-420).

Open in Web View Automation 

cursoragent and others added 3 commits June 22, 2026 12:17
…map files

The JSON.parse call at line 155 of debug-id.ts was unguarded — if a .map
file contained malformed JSON (truncated, corrupt, or not a sourcemap),
the entire sourcemap inject command crashed with an opaque SyntaxError.

Every other JSON.parse in the codebase is wrapped in try/catch. This adds
the same pattern, throwing a descriptive ValidationError that includes the
file path so users know which .map file is problematic.

Co-authored-by: Miguel Betegón <[email protected]>
Both listLogs() and listTraceLogs() passed the user's --limit value
directly as per_page to the Sentry API. When limit > 100, the API
silently caps at 100 items, but the caller's hasMore check
(logs.length >= flags.limit) evaluates to false, hiding remaining data.

This violates the project convention documented in AGENTS.md: 'Never
pass a per_page value larger than API_MAX_PER_PAGE to the API.'

Cap both calls with Math.min(limit, API_MAX_PER_PAGE) to match the
pattern used in autoPaginate() and other list commands.

Co-authored-by: Miguel Betegón <[email protected]>
…list

When multi-page fetching accumulates more results than flags.limit, the
excess items are trimmed with .slice(0, flags.limit) but the API cursor
from the last fetched page is still stored. On '-c next', those trimmed
items are skipped entirely.

This matches the autoPaginate() pattern in infrastructure.ts (lines
419-420) which explicitly drops nextCursor when results overshoot to
prevent skipping items.

Co-authored-by: Miguel Betegón <[email protected]>
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1118/

Built to branch gh-pages at 2026-06-22 12:21 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

Copy link
Copy Markdown
Contributor

Codecov Results 📊

❌ Patch coverage is 71.43%. Project has 5049 uncovered lines.
✅ Project coverage is 81.24%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
src/lib/sourcemap/debug-id.ts 50.00% ⚠️ 2 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    81.24%    81.24%        —%
==========================================
  Files          388       388         —
  Lines        26910     26914        +4
  Branches     17481     17483        +2
==========================================
+ Hits         21861     21865        +4
- Misses        5049      5049         —
- Partials      1822      1822         —

Generated by Codecov Action

Comment on lines +202 to 208
const overshot = results.length > flags.limit;
const hasMore = overshot || !!nextCursor;
// When multi-page fetch overshoots the limit, the API cursor points past
// trimmed items — storing it would skip them on '-c next'. Drop it to
// match autoPaginate() behavior (see infrastructure.ts lines 419-420).
const cursorToStore = !overshot && hasMore ? nextCursor : undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasMore = true when overshot but no cursor stored causes -c next to throw a ValidationError

When the multi-page fetch overshoots flags.limit, hasMore is set to true and the paginationHint prints a -c next hint, but cursorToStore is undefined, so advancePaginationState stores no next entry in the stack. Running --cursor next then hits state.index + 1 >= state.stack.length in resolveCursor and throws "No next page saved for this query" — the opposite of what hasMore: true implies.

Evidence
  • overshot = true → cursorToStore = undefined (line 208); hasMore = true (line 203).
  • advancePaginationState(..., direction='first', undefined) stores stack = [''] with no next entry (pagination.ts:265: nextCursor ? ['', nextCursor] : ['']).
  • outputData.hasMore = true causes paginationHint to emit the -c next hint (revisions.ts line 229).
  • resolveCursor(..., 'next') in pagination.ts:198 checks state.index + 1 >= state.stack.length → 1 >= 1 → throws ValidationError('No next page saved for this query.').
  • autoPaginate() (infrastructure.ts line 419) never exposes hasMore to callers, so the cited comparison does not apply here where hasMore is surfaced directly in CLI output.

Identified by Warden find-bugs · LHQ-E68

@sentry-junior

sentry-junior Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Closing as part of archiving getsentry/cli; the CLI now lives in getsentry/toolkit. The dashboard revisions cursor fix is ported in getsentry/toolkit#1608 (remaining-budget pages, cursor dropped on overshoot), and the sourcemap JSON guard in getsentry/toolkit#1609. The log per_page cap isn't needed anymore because log listing goes through paginate().

@sentry-junior sentry-junior Bot closed this Oct 22, 2026
BYK added a commit to getsentry/toolkit that referenced this pull request Oct 23, 2026
`sentry dashboard revisions --limit 150` fetched two full pages of 100,
trimmed the last 50, and still stored the server cursor. `-c next` then
silently skipped those 50 revisions.

Later pages now request only the remaining budget, the same way the
shared `paginate()` helper does since getsentry/cli#1615. If an endpoint
still returns more than requested, the cursor is dropped, matching
`autoPaginate`.

Ported from the dashboard part of getsentry/cli#1118, which is being
closed with the repo archive.

<!-- junior-request-attribution:start -->
via **BYK**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:local%3Aweb%3Ad9c5b0de1ecf3c7114be7025 -->

--

[View Junior Session in
Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3Ad9c5b0de1ecf3c7114be7025/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: BYK <[email protected]>
BYK added a commit to getsentry/toolkit that referenced this pull request Oct 23, 2026
- `sentry sourcemap inject` crashed with a bare `SyntaxError` when a
companion `.map` file wasn't valid JSON. It now throws a
`ValidationError` that names the file, before touching the JS bundle.
The dry-run path already handled this case.
- `formatRelativeTime` printed the literal text "Invalid Date" for a
timestamp it couldn't parse. It now shows the same muted dash as a
missing timestamp.

Ported from getsentry/cli#1118 and getsentry/cli#1200, which are being
closed with the repo archive. The other fixes in those PRs were already
on main or not worth porting (details in the close comments).

<!-- junior-request-attribution:start -->
via **BYK**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:local%3Aweb%3Ad9c5b0de1ecf3c7114be7025 -->

--

[View Junior Session in
Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3Ad9c5b0de1ecf3c7114be7025/?project=4510944073809921)

<!-- junior-session-footer:end -->

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: BYK <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant