Skip to content

refactor(init): route wizard errors through framework error pipeline#678

Merged
betegon merged 7 commits intomainfrom
refactor/wizard-error-pipeline
Apr 7, 2026
Merged

refactor(init): route wizard errors through framework error pipeline#678
betegon merged 7 commits intomainfrom
refactor/wizard-error-pipeline

Conversation

@betegon
Copy link
Copy Markdown
Member

@betegon betegon commented Apr 7, 2026

Summary

  • Add WizardError class extending CliError with a rendered flag — tells the framework error handler to skip re-displaying errors that clack already showed
  • Replace all 8 process.exitCode = 1 locations in wizard-runner.ts with throw new WizardError(...)
  • Errors now flow through the framework pipeline: telemetry capture via Sentry.captureException, consistent exit code handling, future error improvements apply automatically
  • User cancellation paths (exitCode = 0) are unchanged

Test plan

  • sentry init in a project → cancel at experimental warning → exits 0 (unchanged)
  • sentry init with no network → shows error, exits 1 (now via framework)
  • echo '' | sentry init → shows TTY error, exits 1 (now via WizardError({ rendered: false }))
  • Verify no double error output (clack cancel() + framework error message)

🤖 Generated with Claude Code

Replace direct `process.exitCode = 1` in wizard-runner.ts with thrown
WizardError instances so errors flow through Stricli's error handler,
gaining Sentry telemetry capture and consistent formatting. WizardError
carries a `rendered` flag so clack-displayed errors are not duplicated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 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 ✨

Bug Fixes 🐛

Init

  • Run commands without shell to eliminate injection surface by betegon in #665
  • Use opendir for listDir and validate symlinks during traversal by betegon in #663
  • Rename 'Custom Metrics' feature label to 'Metrics' by MathurAditya724 in #659
  • Add reactFeatures to feature display info by MathurAditya724 in #658
  • Generate spinner messages from payload params instead of server detail by MathurAditya724 in #655

Other

  • (errors) Separate informational notes from actionable alternatives in ContextError by BYK in #651
  • (skill-gen) Eliminate manual maps to prevent undocumented commands by BYK in #670
  • Three bug fixes from Sentry telemetry (CLI-SC, CLI-QZ, CLI-WD) by cursor in #664
  • Fix set-commits --auto, document release workflow pitfalls by BYK in #650

Internal Changes 🔧

Init

  • Route wizard errors through framework error pipeline by betegon in #678
  • Use guardNonInteractive for TTY check by betegon in #677
  • Use shared DRY_RUN_FLAG and add -n alias by betegon in #676
  • Reuse resolveOrg for offline-first org detection by betegon in #666
  • Use mdKvTable and renderMarkdown for wizard summary by betegon in #661

Other

  • Extract createProjectWithDsn to deduplicate project creation by betegon in #667
  • Regenerate skill files and command docs by github-actions[bot] in eb1b19e7

Other

  • Update custom.css by stevenplewis in #653

🤖 This preview updates automatically when you update the PR.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f742575. Configure here.

The server validates DSN and URL fields with z.string().url().
The previous placeholders "(dry-run)" failed Zod validation,
breaking dry-run after the create-sentry-project step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests now expect runWizard to throw WizardError instead of setting
process.exitCode directly. Added a 10s timeout on the describe
block to prevent CI from hanging indefinitely if a test accidentally
waits for interactive input.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
betegon and others added 2 commits April 7, 2026 13:02
When a WizardError thrown inside the wizard loop was caught by
the outer catch block, it would call log.error + cancel again
before re-wrapping. Now WizardError instances are re-thrown
immediately to avoid duplicate output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Codecov Results 📊

134 passed | Total: 134 | Pass Rate: 100% | Execution Time: 0ms

📊 Comparison with Base Branch

Metric Change
Total Tests
Passed Tests
Failed Tests
Skipped Tests

✨ No test changes detected

All tests are passing successfully.

✅ Patch coverage is 100.00%. Project has 1423 uncovered lines.
✅ Project coverage is 95.57%. Comparing base (base) to head (head).

Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    95.56%    95.57%    +0.01%
==========================================
  Files          222       222         —
  Lines        32111     32120        +9
  Branches         0         0         —
==========================================
+ Hits         30686     30697       +11
- Misses        1425      1423        -2
- Partials         0         0         —

Generated by Codecov Action

Comment on lines 524 to 530
`Create one at ${terminalLink(teamsUrl)} and run sentry init again.`
);
cancel("Setup failed.");
process.exitCode = 1;
return null;
throw new WizardError("No teams in your organization.");
}
} else if (teams.length === 1) {
opts = { ...opts, team: (teams[0] as SentryTeam).slug };
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: An outer try...catch block in resolvePreSpinnerOptions swallows a WizardError from a failed team creation, causing the wizard to continue with incomplete configuration.
Severity: HIGH

Suggested Fix

The outer catch block should re-throw the WizardError to ensure the wizard process is properly halted upon team resolution failure. This can be done by checking if (err instanceof WizardError) { throw err; } within the outer catch block.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/lib/init/wizard-runner.ts#L524-L530

Potential issue: In the `resolvePreSpinnerOptions` function, if an organization has no
teams, the wizard attempts to auto-create one. If this creation fails, a `WizardError`
is thrown. However, this error is caught by an outer `try...catch` block that does not
re-throw it. As a result, the function returns the `opts` object without the required
`team` property. The wizard then proceeds with this incomplete configuration,
potentially causing downstream failures or silent misconfiguration, despite logging an
error to the user. This behavior is a regression from the previous implementation which
would have halted execution.

@betegon betegon merged commit 2009674 into main Apr 7, 2026
26 checks passed
@betegon betegon deleted the refactor/wizard-error-pipeline branch April 7, 2026 11:26
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