feat: typed HttpError + input-driven error handling#429
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…orm messages Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
ALagoni97
approved these changes
Jul 23, 2026
Contributor
Author
|
🎉 This PR is included in version 0.79.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the static, hardcoded
handleHttpErrorin the generated HTTP client with an input-driven, typed error contract:HttpError extends Errorclass carrying{ status, statusText, body? }is now exported from everyhttp_client.ts.handleHttpError(status, statusText, body?)throwsHttpError(not a plainError), and itsswitchcases are generated from the error status codes the input document actually declares.fetchcode parses the error response body and forwards it into the thrownHttpError.For OpenAPI inputs, error status codes (
>= 400plusdefault) are aggregated document-wide, each becoming an explicit case with the standard HTTP reason phrase as its message (e.g.400 → 'Bad Request',404 → 'Not Found'). For AsyncAPI inputs (which declare no error responses) the handler is default-only. Any undeclared code falls through to a genericHTTP Error: <status> <statusText>default.Why
The old
handleHttpErrorwas emitted byte-for-byte every run with fixed cases (401/403/404/500) regardless of the input document, and threw a plainError. Consumers had:instanceof),.status/.statusText,body,This makes generated HTTP clients' error handling reflect the actual API spec and gives consumers a first-class, inspectable error type.
Changes
Generator (
src/codegen/)channels/protocols/http/common-types.ts— add the exportedHttpErrorclass; add a generator-sideHTTP_REASON_PHRASESmap and arenderHandleHttpErrorBodyhelper; changerenderHttpCommonTypesto the object-parameter form{ securitySchemes, errorStatusCodes }; emit an input-drivenhandleHttpError(status, statusText, body?).channels/openapi.ts— addcollectErrorStatusCodes/collectResponseErrorCodesto gather declared error codes (>= 400+default) document-wide and thread them intorenderHttpCommonTypes.channels/protocols/http/client.ts— the per-operation error branch now reads the body defensively (await response.json().catch(() => undefined)) and forwards it tohandleHttpError.Tests
methods,retry,openapi) to assert the typed contract (instanceof HttpError,.status,.statusText,.body, message form).'Unauthorized'where the OAuth2 refresh branch throws its own error beforehandleHttpError).400/404/405+ reason phrases; AsyncAPI default-only) and refreshed the channel snapshots.Example & docs
examples/openapi-http-clientwith the typedHttpErrorand added aninstanceof HttpErrordemo. (Regeneration also picked up pre-existing drift: Modelinanext.14payload changes and aserver → baseUrlcontext-field rename; the hand-written demo and README were updated to match.)docs/protocols/http_client.md.Testing
npm run build— passes.npm run lint— passes (0 warnings, incl.typecheck:test).npm test— 53 suites, 675 passed / 1 skipped, 78 snapshots.cd test/runtime/typescript && npm run test:http— 15 suites, 114 passed.npm run generate:assetsproduces noschemas/diff (no Zod config changed), confirming schemas don't need regeneration.http_clientconfig exists intest/blackbox/, so not applicable (behavior is covered by unit + runtime).Per repo memory, the
npm ci-gatedprepare:prstep can fail on pre-existing runtime lockfile drift; the individual quality-gate steps above were run and validated directly instead.Notes
http_client.tschanges shape:HttpErrorclass;handleHttpErrornow takes(status, statusText, body?)and throwsHttpErrorinstead ofError;switchcases are input-derived (OpenAPI) or default-only (AsyncAPI);Consumers catching
Errorstill catchHttpError(it's a subclass). Code asserting exact error messages on AsyncAPI-generated clients will now see theHTTP Error: <status> <statusText>default form (previously'Not Found'/'Forbidden'/'Internal Server Error') unless those codes are declared in the input. The title omits!; if semantic-release needs it, this note documents the breaking nature — add aBREAKING CHANGE:commit footer on squash-merge if a major bump is required.Unchanged: the success-path
unmarshalByStatusCodemechanism,RetryConfig/retryableStatusCodes, theonErrorhook signature, and the OAuth2 401-refresh branch. No new Zod config / opt-in flag. No other protocols or generators touched.