Skip to content

fix(issue-list): propagate original errors instead of wrapping in plain Error#254

Merged
BYK merged 1 commit intomainfrom
fix/issue-list-error-propagation
Feb 17, 2026
Merged

fix(issue-list): propagate original errors instead of wrapping in plain Error#254
BYK merged 1 commit intomainfrom
fix/issue-list-error-propagation

Conversation

@BYK
Copy link
Member

@BYK BYK commented Feb 17, 2026

Summary

Fixes the highest-volume production telemetry issue ("Failed to fetch issues from N project(s)" — CLI-3Q: 132 events, CLI-N: 81 events).

The root cause: fetchIssuesForTarget() caught all errors and discarded the original ApiError, re-throwing a plain Error. This meant telemetry always called captureException (no suppression rule matched), and JSON output lost the HTTP status code.

Changes

  • Propagate ApiError instead of plain Error when all project fetches fail, so the telemetry layer (isClientApiError() from fix(telemetry): skip Sentry reporting for 4xx API errors #251) correctly suppresses 4xx client errors
  • Surface partial failures in multi-project mode: JSON output returns { issues, errors } with raw HTTP status codes; human output warns on stderr
  • Preserve original error details: status code, detail message, and endpoint flow through to the re-thrown error

JSON error format

When some project fetches fail, JSON output includes error details with raw HTTP status codes (not string classifications):

{
  "issues": [...],
  "errors": [
    { "status": 400, "message": "Invalid query syntax" },
    { "message": "Network timeout" }
  ]
}

status is present only for API errors. Non-API errors (network, etc.) have only message.

Test plan

7 new tests in test/commands/issue/list.test.ts:

  • Error propagation: 400, 404, 429 all re-throw as ApiError with correct status
  • Detail preservation: ApiError.detail flows through
  • Partial failure JSON: includes { issues, errors } with status field
  • Partial failure stderr: human output warns about failed projects
  • No-failure backward compat: JSON is a plain array

All 1721 unit tests pass. Typecheck and lint clean.

Depends on #251 for full telemetry suppression of 4xx errors in production.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 17, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Build

  • Add hole-punch tool to reduce compressed binary size by BYK in #245
  • Add gzip-compressed binary downloads by BYK in #244

Other

  • (args) Parse Sentry web URLs as CLI arguments by BYK in #252

Bug Fixes 🐛

Telemetry

  • Reduce noise from version-check JSON parse errors by BYK in #253
  • Skip Sentry reporting for 4xx API errors by BYK in #251
  • Handle EPIPE errors from piped stdout gracefully by BYK in #250
  • Upgrade Sentry SDK to 10.39.0 and remove custom patches by BYK in #249

Other

  • (db) Handle readonly database gracefully instead of crashing by betegon in #235
  • (issue-list) Propagate original errors instead of wrapping in plain Error by BYK in #254
  • (polyfill) Add exited promise and stdin to Bun.spawn Node.js polyfill by BYK in #248
  • (project-list) Add pagination and flexible target parsing by BYK in #221
  • (upgrade) Remove v prefix from release URLs and work around Bun.write streaming bug by BYK in #243

Internal Changes 🔧

  • (build) Replace local hole-punch script with binpunch package by BYK in #246
  • Use @sentry/api client for requests by MathurAditya724 in #226

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 17, 2026

Codecov Results 📊

✅ Patch coverage is 94.29%. Project has 3693 uncovered lines.
✅ Project coverage is 73.06%. Comparing base (base) to head (head).

Files with missing lines (70)
File Patch % Lines
human.ts 58.29% ⚠️ 395 Missing
resolve-target.ts 27.46% ⚠️ 317 Missing
api-client.ts 70.26% ⚠️ 221 Missing
list.ts 23.47% ⚠️ 212 Missing
oauth.ts 30.94% ⚠️ 183 Missing
plan.ts 19.37% ⚠️ 154 Missing
resolver.ts 3.23% ⚠️ 120 Missing
list.ts 67.32% ⚠️ 116 Missing
help.ts 19.85% ⚠️ 109 Missing
upgrade.ts 61.37% ⚠️ 107 Missing
view.ts 40.23% ⚠️ 104 Missing
interactive-login.ts 9.17% ⚠️ 99 Missing
errors.ts 5.94% ⚠️ 95 Missing
view.ts 25.81% ⚠️ 92 Missing
view.ts 39.44% ⚠️ 86 Missing
clipboard.ts 4.49% ⚠️ 85 Missing
status.ts 24.07% ⚠️ 82 Missing
migration.ts 47.44% ⚠️ 82 Missing
list.ts 27.18% ⚠️ 75 Missing
browser.ts 4.11% ⚠️ 70 Missing
login.ts 33.33% ⚠️ 64 Missing
list.ts 86.12% ⚠️ 64 Missing
span-tree.ts 5.00% ⚠️ 57 Missing
explain.ts 33.33% ⚠️ 56 Missing
api.ts 89.80% ⚠️ 47 Missing
upgrade.ts 66.91% ⚠️ 46 Missing
seer.ts 75.54% ⚠️ 45 Missing
refresh.ts 40.63% ⚠️ 38 Missing
schema.ts 90.98% ⚠️ 37 Missing
seer.ts 79.87% ⚠️ 30 Missing
preload.ts 53.23% ⚠️ 29 Missing
view.ts 87.27% ⚠️ 28 Missing
telemetry.ts 93.01% ⚠️ 27 Missing
utils.ts 88.94% ⚠️ 25 Missing
view.ts 61.54% ⚠️ 25 Missing
fix.ts 89.29% ⚠️ 24 Missing
detector.ts 90.10% ⚠️ 20 Missing
arg-parsing.ts 89.29% ⚠️ 18 Missing
binary.ts 88.67% ⚠️ 17 Missing
list.ts 91.16% ⚠️ 16 Missing
list.ts 90.70% ⚠️ 16 Missing
help.ts 57.14% ⚠️ 15 Missing
sentry-client.ts 92.17% ⚠️ 13 Missing
dsn-cache.ts 94.62% ⚠️ 12 Missing
code-scanner.ts 96.25% ⚠️ 12 Missing
logout.ts 56.00% ⚠️ 11 Missing
token.ts 52.17% ⚠️ 11 Missing
qrcode.ts 33.33% ⚠️ 10 Missing
fs-utils.ts 57.14% ⚠️ 9 Missing
view.ts 94.70% ⚠️ 7 Missing
project-root.ts 97.73% ⚠️ 7 Missing
version-check.ts 92.47% ⚠️ 7 Missing
feedback.ts 84.21% ⚠️ 6 Missing
auth.ts 95.56% ⚠️ 6 Missing
shell.ts 96.23% ⚠️ 6 Missing
app.ts 93.90% ⚠️ 5 Missing
setup.ts 97.84% ⚠️ 4 Missing
list.ts 97.33% ⚠️ 4 Missing
project-aliases.ts 97.40% ⚠️ 2 Missing
project-root-cache.ts 96.92% ⚠️ 2 Missing
output.ts 89.47% ⚠️ 2 Missing
alias.ts 99.42% ⚠️ 1 Missing
completions.ts 99.37% ⚠️ 1 Missing
index.ts 98.99% ⚠️ 1 Missing
env-file.ts 99.19% ⚠️ 1 Missing
parser.ts 98.63% ⚠️ 1 Missing
colors.ts 98.21% ⚠️ 1 Missing
trace.ts 99.16% ⚠️ 1 Missing
region.ts 97.30% ⚠️ 1 Missing
helpers.ts 94.74% ⚠️ 1 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    71.21%    73.06%    +1.85%
==========================================
  Files          111       111         —
  Lines        13764     13707       -57
  Branches         0         0         —
==========================================
+ Hits          9801     10014      +213
- Misses        3963      3693      -270
- Partials         0         0         —

Generated by Codecov Action

…ailures

When all project fetches fail, re-throw the original ApiError (with
status, detail, endpoint) instead of a plain Error. This lets the
telemetry layer in PR #251 correctly classify 4xx errors as client
errors and suppress them from Sentry exceptions.

Also:
- Classify more HTTP status codes (404, 429, other 4xx) instead of
  lumping everything into "unknown"
- Include partial failure info in JSON output when some projects fail
- Warn on stderr about partial failures in human output
- Add tests for error propagation and partial failure handling
@BYK BYK force-pushed the fix/issue-list-error-propagation branch from bfc1739 to 027bf80 Compare February 17, 2026 09:54
@BYK BYK changed the title fix(issue-list): propagate ApiError instead of plain Error on fetch failures fix(issue-list): propagate original errors instead of wrapping in plain Error Feb 17, 2026
@BYK BYK marked this pull request as ready for review February 17, 2026 10:36
@BYK BYK merged commit 0a7c420 into main Feb 17, 2026
24 checks passed
@BYK BYK deleted the fix/issue-list-error-propagation branch February 17, 2026 21:30
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