feat(errors)!: rebuild errors module on @vercel/error#15
Conversation
Adopt @vercel/error as the structured-error foundation. CliError now extends VercelError, gaining reason/hint/fix/link/metadata/cause context, environment-aware terminal formatting, and createErrors() factory compatibility via ErrorClass. BREAKING CHANGE: CliError's constructor is now (message, options) instead of (message, code, suggestions); suggestions is replaced by hint/fix. The ErrorOutput payload drops help in favor of reason/hint/fix/link (legacy suggestions from older toolkit copies still map onto hint). errorOutput() takes a details object instead of a suggestions array, and validateFormat's message moved its supported-formats list into fix.
|
Warning Review limit reached
Next review available in: 43 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
There was a problem hiding this comment.
No issues found across 12 files
Architecture diagram
sequenceDiagram
participant UserCode as User Code
participant CliError as CliError (extends VercelError)
participant VercelError as VercelError (@vercel/error)
participant toErrorOutput as toErrorOutput()
participant exitCodeForError as exitCodeForError()
participant Environment as Environment (TTY/pipe)
participant createErrors as createErrors Factory
participant OutputModule as Output Module (toon/json)
participant ProcessExit as Process Exit Code
Note over UserCode,ProcessExit: Primary throw–catch flow
UserCode->>CliError: new CliError('msg', { code:'NOT_FOUND', reason:'', hint:'', fix:'', link:'' })
CliError->>VercelError: super(message, options) with code default UNKNOWN_ERROR
VercelError-->>CliError: VercelError instance (name='CliError', code, reason, hint, fix, link, cause, ...)
UserCode->>toErrorOutput: catch(error) → toErrorOutput(error)
toErrorOutput->>VercelError: isVercelError(error) → true (CliError extends VercelError)
toErrorOutput->>CliError: extract code, reason, hint, fix, link (context fields)
alt Legacy cross‑version CliError (pre‑@vercel/error shape)
toErrorOutput->>CliError: check (error as any).suggestions array → join into hint string
end
toErrorOutput-->>UserCode: ErrorOutput { error, code, reason?, hint?, fix?, link? }
UserCode->>OutputModule: outputData(ErrorOutput, 'toon'/'json')
OutputModule-->>UserCode: Rendered structured output
UserCode->>exitCodeForError: process.exitCode = exitCodeForError(error)
exitCodeForError->>VercelError: hasCode(error, 'VALIDATION_ERROR')
alt error.code === 'VALIDATION_ERROR'
exitCodeForError-->>UserCode: return 2
else
exitCodeForError-->>UserCode: return 1
end
UserCode->>ProcessExit: process.exit(exitCode)
Note over UserCode,ProcessExit: Environment‑aware toString() (inherited from VercelError)
UserCode->>CliError: error.toString()
CliError->>Environment: check isTTY and NO_COLOR
alt TTY and color allowed
Environment-->>CliError: Use ANSI colored tree format
else Piped or NO_COLOR
Environment-->>CliError: Use plain indented text (no ANSI)
end
CliError-->>UserCode: Formatted string
Note over UserCode,createErrors: Factory usage (optional)
UserCode->>createErrors: createErrors({ scope:'gh-please', ErrorClass:CliError, docsBaseUrl:'...' })
createErrors-->>UserCode: errors object with raise() method
UserCode->>CliError: errors.raise('msg', { code:'NOT_FOUND' })
CliError->>VercelError: constructor sets link=docsBaseUrl+'/'+code
VercelError-->>CliError: Structured error with derived link
CliError-->>UserCode: thrown
Note over UserCode,ProcessExit: Re‑exported primitives available from './errors'
Note over UserCode: VercelError, createErrors, isVercelError, hasCode, getMessage, getRootCause, etc.
Greptile SummaryRebuilds the
Confidence Score: 5/5The change is safe to merge; all breaking-change call sites are updated, dispatch logic is correct, and the test suite covers all dispatch paths including cross-bundle and legacy-format scenarios. The dispatch ordering in toErrorOutput is sound — CliError extends VercelError, so real CliError instances always satisfy isVercelError first; the structural fallback only fires for legacy or foreign-bundle copies. The declare readonly code: string narrowing is TypeScript-only and correct at runtime. exitCodeForError's shift to hasCode is an intentional, tested broadening. No silent data loss, no incorrect branch reachability, no missing field propagation. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["toErrorOutput(error)"] --> B{"isVercelError?"}
B -->|yes| C["Extract: message, code, reason, hint, fix, link"]
C --> D["errorOutput with full context"]
B -->|no| E{"isCliError? structural name+code check"}
E -->|yes| F["Read suggestions array"]
F --> G{"suggestions present?"}
G -->|yes| H["legacyHint = suggestions.join newline"]
G -->|no| I["legacyHint = undefined"]
H --> J["errorOutput with legacyHint ?? error.hint"]
I --> J
E -->|no| K["getMessage(error) ?? String(error)"]
K --> L["errorOutput with UNKNOWN_ERROR"]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["toErrorOutput(error)"] --> B{"isVercelError?"}
B -->|yes| C["Extract: message, code, reason, hint, fix, link"]
C --> D["errorOutput with full context"]
B -->|no| E{"isCliError? structural name+code check"}
E -->|yes| F["Read suggestions array"]
F --> G{"suggestions present?"}
G -->|yes| H["legacyHint = suggestions.join newline"]
G -->|no| I["legacyHint = undefined"]
H --> J["errorOutput with legacyHint ?? error.hint"]
I --> J
E -->|no| K["getMessage(error) ?? String(error)"]
K --> L["errorOutput with UNKNOWN_ERROR"]
Reviews (2): Last reviewed commit: "chore(errors): apply AI code review sugg..." | Re-trigger Greptile |
- carry reason/hint/fix/link through the structural isCliError fallback so a VercelError-derived copy that slips past isVercelError doesn't silently lose context fields (suggestions still wins for hint) - assert all four context fields explicitly on the CliError path in toErrorOutput tests, plus the foreign new-style copy fallback - ignore .impeccable local tool cache in eslint and git
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |



Summary
Adopts
@vercel/erroras the structured-error foundation for theerrorsmodule.CliErrornow extendsVercelError— beyondcode, every error can carry the full structured context:reason(why),hint(what could help),fix(how to resolve),link(docs), plusmetadata,attributes, andcausechaining.codestill always defaults toUNKNOWN_ERROR.toString()prints a colored tree on a TTY and plain indented text when piped (NO_COLORrespected), with ANSI/OSC sanitization at render boundaries.createErrors()factory compatibility —CliErroraccepts(message, options)so it plugs intocreateErrors({ ErrorClass: CliError, scope, docsBaseUrl })for per-tool scoping and code-derived docs links.VercelError,createErrors,isVercelError,hasCode,getMessage,getRootCause, ...) from./errorsand the root entry, so consumers don't need a direct dependency.exitCodeForErrornow useshasCode, so any error-like value taggedVALIDATION_ERRORmaps to exit code 2 — not justCliErrorinstances.Breaking changes
CliErrorconstructor:(message, code, suggestions)→(message, options);suggestionsis replaced byhint/fix.ErrorOutputpayload:{ error, code, help? }→{ error, code, reason?, hint?, fix?, link? }. Legacysuggestionsfrom older toolkit copies (cross-version boundary) still map ontohint.errorOutput(message, code, details?)takes a details object instead of a suggestions array.validateFormatmoved the supported-formats list from the message intofix.Notes on the dependency
@vercel/error@0.0.2is an early-stage vercel-labs package;^0.0.2effectively pins it (caret on 0.0.x), it has zero runtime dependencies, and itslefthookpostinstall stays blocked by Bun.Test plan
bun test— 176 passtsc --noEmit,eslint .cleanbun run build+ smoke test againstdist/: structured payload, factorydocsBaseUrllink derivation, validation exit code 2, TTY tree formatting all verified end-to-endSummary by cubic
Rebuilt the errors module on
@vercel/errorto provide richer structured errors and consistent, environment-aware rendering. Updated the API and output shape to carryreason/hint/fix/linkand improve exit-code mapping.New Features
CliErrornow extendsVercelError; always hascode(defaults toUNKNOWN_ERROR) plusreason,hint,fix,link,metadata, andcause.toString()output (colors on TTY, plain when piped).createErrorscompatibility and re-exports ofVercelError, guards (isVercelError,isError,isErrorLike,hasCode), and helpers (getMessage,getRootCause) from the toolkit.exitCodeForErroruseshasCodeso anyVALIDATION_ERRORreturns 2;toErrorOutputpreserves context forVercelErrorand foreignCliErrorcopies, and maps legacysuggestionstohint(suggestions win if both are present).Migration
new CliError(message, code, suggestions)withnew CliError(message, { code, hint?, fix?, reason?, link? }).errorOutput(message, code, details?); payload is{ error, code, reason?, hint?, fix?, link? }. Read these fields in consumers.fix.createErrors,VercelError, and guards from@pleaseai/cli-toolkit/errors; no direct@vercel/errordependency needed.Written for commit 9f03e73. Summary will update on new commits.