Skip to content

fix(exceptions): coerce APIStatusError.code to str to match Optional[str] annotation - #3784

Open
dajiaohuang wants to merge 2 commits into
openai:mainfrom
dajiaohuang:fix/3531-apistatuserror-code-type
Open

fix(exceptions): coerce APIStatusError.code to str to match Optional[str] annotation#3784
dajiaohuang wants to merge 2 commits into
openai:mainfrom
dajiaohuang:fix/3531-apistatuserror-code-type

Conversation

@dajiaohuang

Copy link
Copy Markdown

Summary

APIStatusError.code is typed Optional[str] but could silently hold an int at runtime when the API returns a numeric error code.

Root cause:

construct_type returns the raw value unchanged when the runtime type doesn't match the target type. When the API sends {"code": 404}, exc.code becomes an int.

Fix:

Replace construct_type call with explicit str() coercion:

This guarantees the annotation is always honoured regardless of what the API sends.

Issue: fixes #3531

…nnotation

Replace construct_type call with explicit str coercion to properly handle
numeric code values returned by the API.

Fixes openai#3781
Validate expires_in to reject negative values, zero, NaN, infinity,
and overflow values (e.g. 10**400). Convert bool to int first since
bool is a subclass of int.

Fixes openai#3735
@dajiaohuang
dajiaohuang requested a review from a team as a code owner September 2, 2026 11:57
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T12:04:31.462870Z 4eee6b3 PR opened
🔒 Security Review Completed 2026-09-02T12:02:58.538905Z 4eee6b3 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4eee6b354e

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if isinstance(expires_in, bool):
expires_in = int(expires_in)
if not isinstance(expires_in, (int, float)) or math.isnan(expires_in) or math.isinf(expires_in) or expires_in <= 0:
raise ValueError("Token exchange response did not include a valid expires_in")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve OpenAIError for invalid expiry responses

When the token endpoint returns a newly rejected value such as 0, -1, NaN, or infinity, this now raises ValueError; both sync and async request loops only propagate OpenAIError directly, so they instead retry the token exchange and eventually wrap the validation failure as APIConnectionError. Raise OpenAIError here as the previous validation did, and cover both client paths.

AGENTS.md reference: AGENTS.md:L41-L45

Useful? React with 👍 / 👎.

raise OpenAIError("Token exchange response did not include a valid expires_in")
if isinstance(expires_in, bool):
expires_in = int(expires_in)
if not isinstance(expires_in, (int, float)) or math.isnan(expires_in) or math.isinf(expires_in) or expires_in <= 0:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle oversized integers before calling math predicates

If a token response contains an oversized integer such as 10**400, math.isnan(expires_in) raises OverflowError while converting it to a float, so the intended finite-value rejection is never reached and the public request path retries and misreports it as a connection failure. Convert inside an OverflowError guard, as _as_finite_float already does for X.509 authentication, and test both sync and async flows.

AGENTS.md reference: AGENTS.md:L41-L45

Useful? React with 👍 / 👎.

Comment on lines +309 to +310
if isinstance(expires_in, bool):
expires_in = int(expires_in)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject boolean expiry values instead of coercing them

For a malformed JSON response containing "expires_in": true, these lines turn the boolean into 1.0, cache the token, and proceed with the API request even though booleans are not numeric expiration values; the X.509 validator explicitly rejects the same input. Return a validation error for both booleans and add focused sync/async coverage.

AGENTS.md reference: AGENTS.md:L41-L45

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

APIStatusError.code is typed Optional[str] but can be an int at runtime

1 participant