Skip to content

fix: three bug fixes — null guard crashes, silent catches, NaN metadata#1270

Draft
cursor[bot] wants to merge 4 commits into
mainfrom
cursor/sentry-cli-bug-fixes-ed58
Draft

fix: three bug fixes — null guard crashes, silent catches, NaN metadata#1270
cursor[bot] wants to merge 4 commits into
mainfrom
cursor/sentry-cli-bug-fixes-ed58

Conversation

@cursor

@cursor cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Three independent defensive-coding fixes found via codebase analysis.


1. formatIssueCell and formatAuthStatus crash on null API fields

Root cause: escapeMarkdownInline(issue.title) in formatIssueCell() calls .replace() — crashes with TypeError when the API returns a null title. Same pattern with org.name in auth status display.

Reproduction: sentry issue list when any issue in the response has title: null (can happen with deleted/malformed issues). sentry auth status when any org has name: null.

Fix: Add ?? "" and || "(unnamed)" guards matching existing patterns in the same file (formatIssueDetails at line 806, formatOrgDetails at line 1486).

Files: src/lib/formatters/human.ts


2. Silent catch blocks in dashboard/create.ts and response-cache.ts

Root cause: enrichTargetProjectIds() in dashboard/create.ts silently drops projects when getProject() fails — the dashboard is created without the expected project scope with no diagnostic trail. invalidateCachedResponsesMatching() in response-cache.ts has three catch blocks that swallow all errors silently, making cache corruption invisible.

Reproduction: sentry dashboard create with auto-detect when a project API call fails (network glitch, permissions). Cache invalidation failures are invisible in debug logs.

Fix: Add log.debug() calls to all silent catches, matching the project's documented catch-block policy (AGENTS.md).

Files: src/commands/dashboard/create.ts, src/lib/response-cache.ts


3. NaN timestamps from corrupted numeric metadata

Root cause: Number() on a non-numeric string returns NaN. In version-check.ts, NaN lastChecked causes Date.now() - NaN → NaN, making all comparisons false and permanently disabling version checks with no visible indication. Same pattern in install-info.ts for recordedAt.

Reproduction: Database corruption or manual edits that store non-numeric strings in the metadata table for version check timestamps.

Fix: Add Number.isNaN() guards that fall back to null/0, restoring the "never checked" / "epoch" state so the next check runs normally.

Files: src/lib/db/version-check.ts, src/lib/db/install-info.ts


Test verification

  • All 77 human formatter tests pass
  • All 53 version-check + install-info tests pass
  • All 36 response-cache tests pass (including invalidateCachedResponsesMatching)
  • Lint passes (biome check)
Open in Web View Automation 

cursoragent and others added 4 commits July 20, 2026 12:11
formatIssueCell() passed issue.title directly to escapeMarkdownInline()
which calls .replace() — crashes with TypeError when the API returns a
null title. The same file already guards this in formatIssueDetails()
(issue.title ?? "").

Similarly, formatAuthStatus() passed org.name without a fallback, while
formatOrgDetails() in the same file already uses org.name || "(unnamed)".

Add matching null guards to both call sites.

Co-authored-by: Miguel Betegón <miguelbetegongarcia@gmail.com>
dashboard/create.ts: enrichTargetProjectIds() silently dropped projects
when getProject() failed — the dashboard could be created without the
expected project scope and no diagnostic trail. Add log.debug() so
failures are visible with --verbose.

response-cache.ts: invalidateCachedResponsesMatching() had three silent
catch blocks (parse error, unlink race, outer IO) that swallowed all
errors. Cache corruption or permission issues were invisible. Add
log.debug() calls matching the project's documented catch-block policy.

Co-authored-by: Miguel Betegón <miguelbetegongarcia@gmail.com>
Number() on a non-numeric string (e.g. from DB corruption or manual
edits) returns NaN. In version-check.ts, NaN lastChecked causes
Date.now() - NaN → NaN, making all comparisons false and permanently
disabling version checks with no visible indication.

Similarly, NaN lastNotified permanently suppresses update notifications.
In install-info.ts, NaN recordedAt would break any downstream timestamp
comparisons.

Add Number.isNaN() guards that fall back to null/0, restoring the
'never checked' / 'epoch' state so the next check runs normally.

Co-authored-by: Miguel Betegón <miguelbetegongarcia@gmail.com>
Co-authored-by: Miguel Betegón <miguelbetegongarcia@gmail.com>
@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-1270/

Built to branch gh-pages at 2026-07-20 12:18 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

Copy link
Copy Markdown
Contributor

Codecov Results 📊

❌ Patch coverage is 77.78%. Project has 5481 uncovered lines.
✅ Project coverage is 81.67%. Comparing base (base) to head (head).

Files with missing lines (3)
File Patch % Lines
src/commands/dashboard/create.ts 50.00% ⚠️ 1 Missing
src/lib/formatters/human.ts 100.00% ⚠️ 1 partials
src/lib/response-cache.ts 75.00% ⚠️ 1 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    81.67%    81.67%        —%
==========================================
  Files          426       426         —
  Lines        29896     29903        +7
  Branches     19420     19434       +14
==========================================
+ Hits         24416     24422        +6
- Misses        5480      5481        +1
- Partials      2035      2035         —

Generated by Codecov Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant