Skip to content

fix(compat): coerce by_alias=None to False in model_dump to fix TypeError with pydantic v2#2999

Open
NIK-TIGER-BILL wants to merge 1 commit intoopenai:mainfrom
NIK-TIGER-BILL:fix/model-dump-by-alias-none-type-error
Open

fix(compat): coerce by_alias=None to False in model_dump to fix TypeError with pydantic v2#2999
NIK-TIGER-BILL wants to merge 1 commit intoopenai:mainfrom
NIK-TIGER-BILL:fix/model-dump-by-alias-none-type-error

Conversation

@NIK-TIGER-BILL
Copy link

Summary

Fixes #2921

Problem

model_dump() in _compat.py declares by_alias: bool | None = None and was forwarding the value as-is to pydantic's model_dump(). pydantic-core's Rust-based serializer (pydantic v2) does not accept None for by_alias and raises:

TypeError: argument 'by_alias': 'NoneType' object cannot be converted to 'PyBool'

This error only manifests when DEBUG-level logging is enabled on the openai logger, because the affected call site omits by_alias (so it defaults to None) and is inside a if log.isEnabledFor(logging.DEBUG) block in _base_client.py.

Fix

Coerce None to False before passing to pydantic:

# Before
by_alias=by_alias

# After
by_alias=bool(by_alias) if by_alias is not None else False

The pydantic v1 code path already used bool(by_alias), so this aligns both branches.

Testing

import logging
logging.basicConfig(level=logging.DEBUG)
from openai import OpenAI
client = OpenAI(api_key="fake")
client.chat.completions.create(model="gpt-4.1", messages=[{"role": "user", "content": "hi"}])
# No longer raises TypeError — proceeds to the network request

Fixes openai#2921

model_dump() in _compat.py declares by_alias as bool | None = None
and was forwarding the value as-is to pydantic's model_dump(). pydantic-core's
Rust-based serializer (pydantic v2) does not accept None for by_alias and
raises:

  TypeError: argument 'by_alias': 'NoneType' object cannot be converted
  to 'PyBool'

This error only manifests when DEBUG-level logging is enabled on the
openai logger, because the call that omits by_alias is inside a
'if log.isEnabledFor(logging.DEBUG)' block in _base_client.py.

Fix: replace 'by_alias=by_alias' with an explicit coercion so that None
becomes False (the natural default) instead of being forwarded to pydantic:

    by_alias=bool(by_alias) if by_alias is not None else False

The pydantic v1 code path already used bool(by_alias), so this aligns
both branches.
@NIK-TIGER-BILL NIK-TIGER-BILL requested a review from a team as a code owner March 21, 2026 07:12
Copy link

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

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: bee7537f80

ℹ️ 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".

warnings=True if PYDANTIC_V1 else warnings,
by_alias=by_alias,
# pydantic-core's Rust serializer rejects None for by_alias; coerce to bool.
by_alias=bool(by_alias) if by_alias is not None else False,

Choose a reason for hiding this comment

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

P2 Badge Preserve config-driven alias behavior in model_dump

When by_alias is omitted, supported Pydantic 2.11+ models can still serialize aliases via ConfigDict(serialize_by_alias=True). Forcing None to False here changes that contract: _compat.model_dump() no longer defers to the model config, and both _utils._transform._transform_recursive() and _async_transform_recursive() call this helper for arbitrary pydantic.BaseModel inputs when building request bodies. In that scenario, aliased third-party Pydantic models will now emit field names instead of aliases, which can send the wrong keys to the API.

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.

Bug: by_alias: NoneType in openai-python v2.24.0 when logging.DEBUG is enabled

1 participant