langchain - 💡(How to fix) Fix AzureChatOpenAI._create_chat_result emits PydanticSerializationUnexpectedValue warnings for structured-output responses

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

#35543 added exclude={"choices": {"__all__": {"message": {"parsed"}}}} to BaseChatOpenAI._create_chat_result's response.model_dump() call to suppress PydanticSerializationUnexpectedValue warnings on structured-output responses.

AzureChatOpenAI._create_chat_result overrides the base method (to inspect Azure-specific content-filter metadata) and runs a second response.model_dump() on the same response without the same exclusion. Every Azure with_structured_output call therefore still emits the warning on this second dump. In our deployment these warnings show up on every chat-completion call that uses structured output and get ingested by log collectors at ERROR severity from stderr, drowning out real errors.

The fix is to mirror the same exclude into the Azure override. I have a one-line patch + regression test ready (see the closed PR #37632) and can re-open it once an issue is assigned.

Error Message

Error Message and Stack Trace (if applicable)

AzureChatOpenAI._create_chat_result overrides the base method (to inspect Azure-specific content-filter metadata) and runs a second response.model_dump() on the same response without the same exclusion. Every Azure with_structured_output call therefore still emits the warning on this second dump. In our deployment these warnings show up on every chat-completion call that uses structured output and get ingested by log collectors at ERROR severity from stderr, drowning out real errors.

Root Cause

#35543 added exclude={"choices": {"__all__": {"message": {"parsed"}}}} to BaseChatOpenAI._create_chat_result's response.model_dump() call to suppress PydanticSerializationUnexpectedValue warnings on structured-output responses.

AzureChatOpenAI._create_chat_result overrides the base method (to inspect Azure-specific content-filter metadata) and runs a second response.model_dump() on the same response without the same exclusion. Every Azure with_structured_output call therefore still emits the warning on this second dump. In our deployment these warnings show up on every chat-completion call that uses structured output and get ingested by log collectors at ERROR severity from stderr, drowning out real errors.

The fix is to mirror the same exclude into the Azure override. I have a one-line patch + regression test ready (see the closed PR #37632) and can re-open it once an issue is assigned.

Fix Action

Fix / Workaround

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

The fix is to mirror the same exclude into the Azure override. I have a one-line patch + regression test ready (see the closed PR #37632) and can re-open it once an issue is assigned.

Other Dependencies

httpx: 0.28.1 jsonpatch: 1.33 langgraph: 1.2.0 numpy: 2.3.4 openai: 2.32.0 orjson: 3.11.6 packaging: 25.0 pydantic: 2.12.2 pytest: 9.0.3 pytest-asyncio: 1.3.0 pytest-benchmark: 5.0.1 pytest-codspeed: 4.1.1 pytest-recording: 0.13.4 pytest-socket: 0.7.0 pyyaml: 6.0.3 requests: 2.33.0 requests-toolbelt: 1.0.0 rich: 14.2.0 syrupy: 5.1.0 tenacity: 9.1.2 tiktoken: 0.12.0 typing-extensions: 4.15.0 uuid-utils: 0.12.0 vcrpy: 8.1.1 wrapt: 1.17.3 xxhash: 3.6.0 zstandard: 0.25.0

Code Example

import warnings
from typing import Literal

import openai
from pydantic import BaseModel, SecretStr

from langchain_openai import AzureChatOpenAI


class ModelOutput(BaseModel):
    output: str


class MockParsedMessage(openai.BaseModel):
    role: Literal["assistant"] = "assistant"
    content: str = '{"output": "Paris"}'
    parsed: None = None
    refusal: str | None = None


class MockChoice(openai.BaseModel):
    index: int = 0
    finish_reason: Literal["stop"] = "stop"
    message: MockParsedMessage


class MockChatCompletion(openai.BaseModel):
    id: str = "chatcmpl-1"
    object: str = "chat.completion"
    created: int = 0
    model: str = "gpt-4o-mini"
    choices: list[MockChoice]
    usage: dict[str, int] | None = None


parsed_response = ModelOutput(output="Paris")
response = MockChatCompletion.model_construct(
    choices=[
        MockChoice.model_construct(
            message=MockParsedMessage.model_construct(parsed=parsed_response)
        )
    ],
    usage={"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2},
)

llm = AzureChatOpenAI(
    azure_deployment="gpt-4o-mini",
    api_version="2024-10-01-preview",
    azure_endpoint="https://example.openai.azure.com",
    api_key=SecretStr("test"),
)

with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter("always")
    llm._create_chat_result(response)

print(f"# warnings: {len(caught)}")
for w in caught:
    print(w.category.__name__, str(w.message))

---

# warnings: 1
UserWarning Pydantic serializer warnings:
  PydanticSerializationUnexpectedValue(Expected `none` - serialized value may not be as expected [field_name='parsed', input_value=ModelOutput(output='Paris'), input_type=ModelOutput])

---

System Information
------------------
> OS:  Darwin
> OS Version:  Darwin Kernel Version 25.5.0: Mon Apr 27 20:39:42 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T6031
> Python Version:  3.12.10 (main, May 22 2025, 01:38:44) [Clang 20.1.4 ]

Package Information
-------------------
> langchain_core: 1.4.0
> langchain: 1.3.1
> langsmith: 0.8.5
> langchain_openai: 1.2.2
> langchain_protocol: 0.0.14
> langchain_tests: 1.1.9
> langgraph_sdk: 0.3.3

Optional packages not installed
-------------------------------
> deepagents
> deepagents-cli

Other Dependencies
------------------
> httpx: 0.28.1
> jsonpatch: 1.33
> langgraph: 1.2.0
> numpy: 2.3.4
> openai: 2.32.0
> orjson: 3.11.6
> packaging: 25.0
> pydantic: 2.12.2
> pytest: 9.0.3
> pytest-asyncio: 1.3.0
> pytest-benchmark: 5.0.1
> pytest-codspeed: 4.1.1
> pytest-recording: 0.13.4
> pytest-socket: 0.7.0
> pyyaml: 6.0.3
> requests: 2.33.0
> requests-toolbelt: 1.0.0
> rich: 14.2.0
> syrupy: 5.1.0
> tenacity: 9.1.2
> tiktoken: 0.12.0
> typing-extensions: 4.15.0
> uuid-utils: 0.12.0
> vcrpy: 8.1.1
> wrapt: 1.17.3
> xxhash: 3.6.0
> zstandard: 0.25.0
RAW_BUFFERClick to expand / collapse

Submission checklist

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Package

  • langchain-openai

Related Issues / PRs

  • #35538 (original report)
  • #35543 (fix on BaseChatOpenAI._create_chat_result, which missed the Azure override)

Reproduction Steps / Example Code (Python)

import warnings
from typing import Literal

import openai
from pydantic import BaseModel, SecretStr

from langchain_openai import AzureChatOpenAI


class ModelOutput(BaseModel):
    output: str


class MockParsedMessage(openai.BaseModel):
    role: Literal["assistant"] = "assistant"
    content: str = '{"output": "Paris"}'
    parsed: None = None
    refusal: str | None = None


class MockChoice(openai.BaseModel):
    index: int = 0
    finish_reason: Literal["stop"] = "stop"
    message: MockParsedMessage


class MockChatCompletion(openai.BaseModel):
    id: str = "chatcmpl-1"
    object: str = "chat.completion"
    created: int = 0
    model: str = "gpt-4o-mini"
    choices: list[MockChoice]
    usage: dict[str, int] | None = None


parsed_response = ModelOutput(output="Paris")
response = MockChatCompletion.model_construct(
    choices=[
        MockChoice.model_construct(
            message=MockParsedMessage.model_construct(parsed=parsed_response)
        )
    ],
    usage={"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2},
)

llm = AzureChatOpenAI(
    azure_deployment="gpt-4o-mini",
    api_version="2024-10-01-preview",
    azure_endpoint="https://example.openai.azure.com",
    api_key=SecretStr("test"),
)

with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter("always")
    llm._create_chat_result(response)

print(f"# warnings: {len(caught)}")
for w in caught:
    print(w.category.__name__, str(w.message))

The same script invoked against ChatOpenAI produces zero warnings (the fix from #35543 covers that path); against AzureChatOpenAI it produces one.

Error Message and Stack Trace (if applicable)

# warnings: 1
UserWarning Pydantic serializer warnings:
  PydanticSerializationUnexpectedValue(Expected `none` - serialized value may not be as expected [field_name='parsed', input_value=ModelOutput(output='Paris'), input_type=ModelOutput])

Description

#35543 added exclude={"choices": {"__all__": {"message": {"parsed"}}}} to BaseChatOpenAI._create_chat_result's response.model_dump() call to suppress PydanticSerializationUnexpectedValue warnings on structured-output responses.

AzureChatOpenAI._create_chat_result overrides the base method (to inspect Azure-specific content-filter metadata) and runs a second response.model_dump() on the same response without the same exclusion. Every Azure with_structured_output call therefore still emits the warning on this second dump. In our deployment these warnings show up on every chat-completion call that uses structured output and get ingested by log collectors at ERROR severity from stderr, drowning out real errors.

The fix is to mirror the same exclude into the Azure override. I have a one-line patch + regression test ready (see the closed PR #37632) and can re-open it once an issue is assigned.

System Info


System Information
------------------
> OS:  Darwin
> OS Version:  Darwin Kernel Version 25.5.0: Mon Apr 27 20:39:42 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T6031
> Python Version:  3.12.10 (main, May 22 2025, 01:38:44) [Clang 20.1.4 ]

Package Information
-------------------
> langchain_core: 1.4.0
> langchain: 1.3.1
> langsmith: 0.8.5
> langchain_openai: 1.2.2
> langchain_protocol: 0.0.14
> langchain_tests: 1.1.9
> langgraph_sdk: 0.3.3

Optional packages not installed
-------------------------------
> deepagents
> deepagents-cli

Other Dependencies
------------------
> httpx: 0.28.1
> jsonpatch: 1.33
> langgraph: 1.2.0
> numpy: 2.3.4
> openai: 2.32.0
> orjson: 3.11.6
> packaging: 25.0
> pydantic: 2.12.2
> pytest: 9.0.3
> pytest-asyncio: 1.3.0
> pytest-benchmark: 5.0.1
> pytest-codspeed: 4.1.1
> pytest-recording: 0.13.4
> pytest-socket: 0.7.0
> pyyaml: 6.0.3
> requests: 2.33.0
> requests-toolbelt: 1.0.0
> rich: 14.2.0
> syrupy: 5.1.0
> tenacity: 9.1.2
> tiktoken: 0.12.0
> typing-extensions: 4.15.0
> uuid-utils: 0.12.0
> vcrpy: 8.1.1
> wrapt: 1.17.3
> xxhash: 3.6.0
> zstandard: 0.25.0

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING