refactor(cli): centralize error handling with withErrorHandler action wrapper#2713
refactor(cli): centralize error handling with withErrorHandler action wrapper#2713
Conversation
… wrapper Replace duplicated try/catch error handling across 28 CLI commands with a centralized `withErrorHandler` utility that wraps Commander.js action handlers. Closes #2694 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep withErrorHandler wrapper, discard manually added try/catch blocks from main that duplicate the centralized error handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review: PR #2713refactor(cli): centralize error handling with withErrorHandler action wrapper SummaryThis is a high-quality refactoring PR. It introduces a Key FindingsP1 --
|
| Check | Result |
|---|---|
| Mock violations | 0 |
| Test coverage issues | 0 |
| Defensive programming | 0 (28 instances removed) |
| Dynamic imports | 0 |
Type safety (any) |
0 |
| Lint/type suppressions | 0 |
| Hardcoded URLs | 0 |
| Fallback patterns | 0 |
| Internal code mocking | 0 |
Test Quality
- 8 new tests for
withErrorHandlercovering all error branches (UNAUTHORIZED, non-auth API error, plain Error, Error with cause, non-Error throws, argument forwarding) - 14 existing test files updated with correct assertions
- All 803 CLI tests pass
Positive Design Decisions
- Clean generic signature
<T extends unknown[]>preserving argument types - Removal of misleading 403 -> "An unexpected network issue occurred" mapping
- Promotion of auth error from
getHeaders()asApiRequestErrorinstead of plainError - Barrel export pattern for the
commandmodule - Net -94 lines -- textbook YAGNI improvement
Error Message Format Changes
| Scenario | Before (per-command) | After (centralized) |
|---|---|---|
| Auth failure | "✗ Failed to list volumes" + "vm0 auth login" |
"✗ Not authenticated" + "Run: vm0 auth login" |
| API error | "✗ Failed to list volumes" + message |
"✗ {status}: {message}" |
| Generic error | "✗ Failed to list volumes" + message |
"✗ {message}" |
| Non-Error throw | "✗ Failed to list volumes" |
"✗ An unexpected error occurred" |
The new format is more informative (includes HTTP status code) but loses context-specific prefixes. This is a reasonable trade-off since the context is usually obvious from the command being run.
Verdict
Changes Requested -- Please investigate the P1 dev-tool compose --json error output regression before merging. The P2 handlePluginError inconsistency can be addressed in a follow-up.
Full review details: codereviews/20260209/
Reviewed by code-quality analysis on 2026-02-09
Restore structured JSON error output in --json mode by using an inner try/catch, while still delegating human-readable errors to withErrorHandler. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Incorporate --experimental-shared-agent flag validation from main while keeping withErrorHandler wrapper from this branch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review: PR #2713refactor(cli): centralize error handling with withErrorHandler action wrapper SummaryThis PR introduces a The approach is clean and well-aligned with the DRY principle. The new module at Key FindingsNo Critical Issues (P0)No blocking issues found. The refactoring is mechanically straightforward and the test coverage is thorough. Observations (P1)
Nice-to-haves (P2)
Bad Smell Analysis
VerdictLGTM -- This is a well-executed refactoring that reduces duplication, standardizes error display, and improves maintainability. The Reviewed by Claude Code |
Summary
withErrorHandlerutility that wraps Commander.js action handlers with centralized error handlingclient-factory.tsby removing theuseServerMessageoption fromhandleErrorStandardized error display format:
UNAUTHORIZED:✗ Not authenticated+Run: vm0 auth loginApiRequestError:✗ {status}: {message}Error:✗ {message}✗ An unexpected error occurredCause: {cause.message}Result: 47 files changed, net -94 lines of code. All 803 CLI tests pass.
Closes #2694
Test plan
withErrorHandlercovering all error branches@sentry/nodeissue)🤖 Generated with Claude Code