feat(api): error-type predicates + fix rate-limit exit code - #122
Conversation
DX-969 Centralize API error-type matching behind api.Is…(err) predicates
ProblemCLI error handling matches API error types by hardcoded string literals scattered across the codebase —
We already generate the constantsThe v2 OpenAPI spec defines the error
They're just unused — every site hardcodes the raw string instead. ProposalAdd centralized predicate helpers in func IsAlreadyExists(err error) bool
func IsNotFound(err error) bool
func IsParameterError(err error) bool
// + server_error / rate_limit / unauthorized as usefulThen sweep the existing string-literal sites onto them. Call sites become Scope
OriginSurfaced reviewing the paywalls attach/detach PR (cli#111), which hardcodes |
|
bugbot run |
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 83537cd. Configure here.
… code Add IsAlreadyExists/IsNotFound/IsParameterError/IsRateLimited/IsUnauthorized/ IsServerError backed by the generated spec constants, so error classification stops hardcoding type strings — a spec rename now breaks the build instead of silently dropping a match. ExitCodeFor matched only the synthesized rate_limit_exceeded fallback, not the spec's rate_limit_error that a real 429 carries, so real rate-limit errors got exit 1 instead of 6. Routed through IsRateLimited (accepts both), fixing it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The predicate claimed 401/403 but only matched authentication_error (401) and the bodyless fallback, so a real 403 (authorization_error) fell through and ExitCodeFor returned 1 instead of 4. Match the generated ForbiddenType constant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
83537cd to
1bfa876
Compare
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 1bfa876. Configure here.
CLI error handling matched API error types by hardcoded string literals (
apiErr.Type == "resource_missing", etc.), even though the v2 spec's error-type enum is already codegen'd intointernal/api/types_gen.goas constants — they were just unused.Adds predicates in
internal/apibacked by those constants:IsAlreadyExists,IsNotFound,IsParameterError,IsRateLimited,IsUnauthorized,IsServerError. A future spec rename becomes a compile error instead of a silently-dropped match at each call site.Bonus — fixes a real bug.
ExitCodeForonly matched the synthesizedrate_limit_exceededfallback, not the spec'srate_limit_errorthat a real 429 actually carries — so real rate-limit errors returned exit1instead of6.IsRateLimitedaccepts both, so it's fixed and locked by a matrix test case.ExitCodeForis swept onto the predicates now. The other literal sites (paywalls attach/detach from #111, and theparseErrorsynthesized fallbacks) can move over as they land — the predicates already accept the legacy fallback strings, so nothing regresses in the meantime.🤖 Generated with Claude Code
Note
Medium Risk
Changes CLI exit-code mapping for auth, not-found, and rate-limit errors (a script-facing contract). Behavior is expanded (403 and spec 429 now map correctly) rather than narrowed.
Overview
Adds
IsAlreadyExists,IsNotFound,IsParameterError,IsRateLimited,IsUnauthorized, andIsServerErrorso callers classifyAPIErrors via OpenAPI-generated type constants instead of string literals. Spec renames then fail at compile time. Rate-limit and unauthorized predicates also accept the bodyless-4xx fallback strings fromparseError.ExitCodeFornow uses those predicates. That fixes a bug: real 429s carryrate_limit_errorand previously fell through to exit1instead of6. 403authorization_errornow maps to exit4as well. Wrapped errors are classified correctly.Reviewed by Cursor Bugbot for commit 1bfa876. Bugbot is set up for automated code reviews on this repo. Configure here.