🚀 Enhancements
fix(pro): friendlier 4xx error rendering and propagate hints to users @osterman (#2386)
## what- Surface the Atmos Pro server's user-facing 4xx fields (
errorMessage,errorTag,data.validationErrors[]) directly to the CLI user instead of opaqueHTTP 500: API response error: API request failed with status Nnoise. - Render
data.validationErrors[]as a bullet list under the headline (with dedupe of trailing server-side concatenations like"failed: A; B"). - Add a 400 hint linking to
settings.pro.*docs and a drift-detection-specific hint (selected byerrorTag == DriftDetectionValidationErroror substring match on the message). - Drop the redundant
HTTP <code>:prefix inAPIError.Error()for 4xx so output readsUploadInstances: <server message>instead ofUploadInstances: HTTP 400: API response error: <server message>. - Preserve
trace_idon all statuses (including 4xx) so support can correlate user-reported issues. - Tolerate both
errorMessage(current) and legacyerrorfield on responses; newEffectiveErrorMessage()prefers the former. - Replace
errors.Join(sentinel, cause)with a smallwrapErrhelper using the existingerrUtils.Build(...).WithCause(...)pattern. Stdliberrors.Joinandfmt.Errorf("%w: %w", ...)both produce multi-errors that hide cockroach hint annotations fromGetAllHints, which is why the existing 401/403/404/5xx hints never actually rendered to users. - Retry behavior unchanged: 4xx remains non-retryable, 401 still refreshes the OIDC token, 5xx still backs off.
why
- Real user pain: running
atmos list instances --uploadagainst a misconfigured stack producedUploadInstances: HTTP 500: API response error: API request failed with status 500 (trace_id: ...)four times in a row. The server actually returned a clean validation message describing the missing drift-detection workflows, but the CLI couldn't surface it (DTO field-name mismatch + lost hints). - The atmos-pro server now correctly returns 4xx (not 500) with structured
errorMessageanddata.validationErrors[]for user-error conditions; this PR is the CLI side of that contract. - Hints attached via
errUtils.Build(...).WithHint(...)were silently dropped at the outermost wrap layer becauseerrors.Joindoesn't expose its children tocockroachErrors.GetAllHints. Users never saw the lightbulb hints the 401/403/404/5xx code paths were already emitting; this PR makes them visible.
references
N/A
Summary by CodeRabbit
-
New Features
- Richer API error parsing that surfaces structured messages, validation bullets, and drift-detection guidance.
- Unified error-wrapping semantics that preserve original error hints and improve retry exhaustion reporting.
-
Bug Fixes
- Cleaner 4xx error text (removed redundant HTTP prefix) while preserving trace IDs.
- 400 responses are not retried and now surface clearer, deduplicated validation bullets.
- More consistent error handling and ensured response bodies are closed on error.
-
Tests
- Expanded tests covering error rendering, drift-detection cases, retry behavior, and response-body/redirect edge cases.