-
Notifications
You must be signed in to change notification settings - Fork 35
Open
Description
Summary
Improve the generated client's error handling around non-success HTTP responses. Currently each service method checks for a single expected status code and raises HTTPException(status_code, ' failed with status code: <code>') without context, parsed error model, or headers.
Problems With Current Behavior
- Error message lacks HTTP method, path, expected vs actual status.
- Response body is discarded (critical for debugging validation errors, rate limits, auth issues).
- No attempt to parse documented error schemas (e.g.
ErrorResponse). - Headers (rate limit, retry, correlation/request IDs) are not surfaced.
- Only one success code is recognized (often 200/201/204 variations in real APIs).
- No hook for custom retry / logging strategies.
Proposed Enhancements
- Rich HTTPException subclass (e.g.
APIError) with attributes:status_code: intmethod: strpath: strexpected_statuses: list[int]response_headers: dict[str, str]response_text: str(raw body, truncated to e.g. 2KB)error_model: Optional[BaseModel](parsed from first matching error schema if possible)
- Include informative
__str__showing method path status and short body snippet. - Recognize multiple success codes derived from spec (all 2XX responses listed) instead of just the first one.
- Attempt to parse error body:
- Inspect documented non-2xx responses in operation.responses.
- If JSON and schema is a $ref, import & parse into the model (pydantic).
- Attach parsed model (or validation error info) to exception.
- Expose helper
raise_for_status(response, operation_meta)inside generated code to centralize logic. - Optional user hook: allow APIConfig to accept
error_handler: Callable[[APIError], None]invoked before raising (for logging / metrics / custom retry). - Backwards compatibility: keep
HTTPExceptionname but implement new fields; retain current constructor signature; old code catchingHTTPExceptioncontinues to work. - Async parity: mirror behavior for async clients.
Stretch (Optional / Future)
- Auto retry on
429withRetry-Afterrespect (configurable max attempts). - Deserialize XML or text/plain when declared in spec.
- Structured rate-limit info (limit, remaining, reset) extracted into fields.
Acceptance Criteria
- Generated services raise enriched exception containing method, path, status, and truncated body.
- All documented 2xx codes for an operation are accepted without raising.
- If an error schema is defined (e.g.
ErrorResponse), exception contains parsed model. - Unit tests cover: single 200, multiple success codes (200/201), error with JSON model, error with invalid JSON, 429 rate limit header extraction.
- Backwards compatibility test: existing code catching
HTTPExceptionstill works.
Rationale
Better diagnostics accelerates integration debugging and reduces guesswork when consuming generated clients—especially for large OpenAPI 3.1 specs.
Implementation Sketch
- Add new template snippet for a shared
errors.pyin output (or embed in api_config.py for simplicity). - During service generation, collect all success status codes (keys starting with '2').
- Replace inline status check with call to helper that returns early if response.status_code in expected_codes else raises enriched exception.
- Add conditional parsing of error body using the first matching documented non-2xx response schema with a JSON content type.
Let me know if any constraints/preferences before implementation and I can adjust this plan.
Metadata
Metadata
Assignees
Labels
No labels