Skip to content

fix: coerce by_alias to bool in model_dump to prevent TypeError with DEBUG logging#2940

Open
giulio-leone wants to merge 2 commits intoopenai:mainfrom
giulio-leone:fix/model-dump-by-alias-none
Open

fix: coerce by_alias to bool in model_dump to prevent TypeError with DEBUG logging#2940
giulio-leone wants to merge 2 commits intoopenai:mainfrom
giulio-leone:fix/model-dump-by-alias-none

Conversation

@giulio-leone
Copy link

@giulio-leone giulio-leone commented Mar 8, 2026

Summary

Fixes #2921model_dump() raises TypeError: argument 'by_alias': 'NoneType' object cannot be converted to 'PyBool' when DEBUG logging is enabled.

Root Cause

In _compat.py, model_dump() declares by_alias: bool | None = None but passes the value directly to Pydantic v2's model_dump():

# line 152 — passes None to pydantic-core Rust serializer
by_alias=by_alias,  # TypeError when by_alias is None

Fix

Omit by_alias from kwargs when None, preserving Pydantic's model-level default (e.g. ConfigDict(serialize_by_alias=True)). Only forward explicit True/False values:

kwargs = dict(mode=mode, exclude=exclude, ...)
if by_alias is not None:
    kwargs["by_alias"] = by_alias
return model.model_dump(**kwargs)

This preserves tri-state semantics:

  • None → Pydantic uses its model default
  • True/False → explicitly forwarded

Tests

Added test_model_dump_by_alias_none verifying:

  • Default call (implicit by_alias=None) works
  • Explicit by_alias=None works
  • Explicit by_alias=False still forwarded correctly

@giulio-leone giulio-leone requested a review from a team as a code owner March 8, 2026 01:37
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: 4bd22da0f2

ℹ️ 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 are not supported in Pydantic v1
warnings=True if PYDANTIC_V1 else warnings,
by_alias=by_alias,
by_alias=bool(by_alias),

Choose a reason for hiding this comment

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

P2 Badge Preserve tri-state by_alias semantics in model_dump

Coercing by_alias with bool(by_alias) changes the meaning of the default None value from “use model default” to always False, so models that rely on alias serialization defaults (e.g., ConfigDict(serialize_by_alias=True) in Pydantic v2) will now silently emit field names instead of aliases when callers omit by_alias. This is a behavior regression from the previous pass-through and can produce incorrect serialized payloads in any call site using _compat.model_dump(..., by_alias=None) or the default.

Useful? React with 👍 / 👎.

Copy link
Author

Choose a reason for hiding this comment

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

Good catch — updated the fix to omit by_alias entirely when None instead of coercing with bool(). This preserves tri-state semantics so models with ConfigDict(serialize_by_alias=True) keep their default alias behavior.

…TypeError

`model_dump()` in `_compat.py` declares `by_alias: bool | None = None`
but passes the value directly to Pydantic v2's `model_dump()`, which
expects a `bool`. When `by_alias` is `None` (the default), pydantic-core's
Rust serializer raises `TypeError: argument 'by_alias': 'NoneType' object
cannot be converted to 'PyBool'`.

This only manifests when DEBUG logging is enabled, because the affected
call path is inside `_build_request()`'s `log.isEnabledFor(logging.DEBUG)`
block.

Omit `by_alias` from kwargs when `None` so Pydantic uses its model-level
default (preserving tri-state semantics for models with
`ConfigDict(serialize_by_alias=True)`), and only forward explicit
`True`/`False` values.

Fixes openai#2921

Signed-off-by: Giulio Leone <[email protected]>
@giulio-leone
Copy link
Author

Friendly ping — CI is green, tests pass, rebased on latest. Ready for review whenever convenient. Happy to address any feedback. 🙏

Only coerce to bool when by_alias is not None, avoiding loss of
None vs False distinction in the v1 fallback code path.
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