fix(exceptions): support integer error codes in APIError validationfix(exceptions): support integer error codes in APIError validation - #3554
Conversation
Widen APIError.code and ErrorObject.code types from Optional[str] to Optional[Union[str, int]] to prevent runtime validation failures when API error responses return numeric error codes. Add test to verify correct parsing of numeric error codes.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 295bdf163d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| if is_dict(body): | ||
| self.code = cast(Any, construct_type(type_=Optional[str], value=body.get("code"))) | ||
| self.code = cast(Any, construct_type(type_=Optional[Union[str, int]], value=body.get("code"))) |
There was a problem hiding this comment.
Preserve integer error codes under pydantic v1
Because this package still allows pydantic>=1.9.0,<3, environments pinned to pydantic 1.x will run this through v1 Union validation, which tries the str branch first and coerces a JSON integer like 400 to '400' instead of preserving it as an int. In those supported installs, integer API error codes still surface as strings, so callers comparing exc.code == 400 and the new test scenario fail; handle primitive ints explicitly or avoid the str-first Union validation for this field.
Useful? React with 👍 / 👎.
jbeckwith-oai
left a comment
There was a problem hiding this comment.
Two blockers before this is ready:
-
The repository lint gate currently fails.
./scripts/lintreports unsorted imports in both changed source files and the new test, plus an unusedopenaiimport.ruff format --checkalso reports thattests/test_exceptions_custom.pyneeds formatting (including trailing whitespace and missing trailing commas). Please run the repo formatter/linter and commit the result. -
The new runtime test does not exercise the bug this PR fixes. I ran it unchanged against the base commit (
4f404262) and it passes there too: the lenientconstruct_type(Optional[str], 400)path already returns the integer at runtime. The regression is the public type annotation, so please add a static type assertion/typecheck fixture (for example,assert_type(exc_info.value.code, str | int | None)) that fails on the base annotation and passes with this change. That will actually prevent the annotation from silently regressing.
Summary
This PR fixes an issue where error responses containing integer/numeric error codes (e.g.
{"error": {"code": 400}}instead of{"error": {"code": "invalid_request"}}) raise a runtime validation/type error becauseAPIError.codeandErrorObject.codewere strictly typed asOptional[str].This is common when using various OpenAI-compatible gateways or proxy endpoints that return integer codes.
Key Changes
APIError.codeinsrc/openai/_exceptions.pytoOptional[Union[str, int]]and updateconstruct_typeto allow both types.ErrorObject.codeinsrc/openai/types/shared/error_object.pytoOptional[Union[str, int]].tests/test_exceptions_custom.pyto verify that numeric error codes are correctly parsed and mapped to the exception attributes without throwing a type validation error.Closes
APIStatusError.codeis typedOptional[str]but can be anintat runtime #3531