When using client.messages.stream(), calling model_dump() on the message_stop event produces PydanticSerializationUnexpectedValue warnings. this happens on every streamed response
Repro:
import warnings
from anthropic import Anthropic
from anthropic.types.parsed_message import ParsedTextBlock, ParsedMessage
from anthropic.lib.streaming._types import ParsedMessageStopEvent
from anthropic._models import build
import anthropic
# Simulates exactly what build_events() does for message_stop
parsed_msg = ParsedMessage.construct(
id="msg_test", type="message", role="assistant",
content=[ParsedTextBlock.construct(type="text", text="Hello!")],
model="claude-sonnet-4-20250514", stop_reason="end_turn",
usage=anthropic.types.Usage.construct(input_tokens=10, output_tokens=5),
)
event = build(ParsedMessageStopEvent, type="message_stop", message=parsed_msg)
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
event.model_dump()
print(f"{len(caught)} warnings") # 1
print(caught[0].message)
# PydanticSerializationUnexpectedValue: Expected `ParsedTextBlock[TypeVar]` but got `ParsedTextBlock`...
Root cause:
In lib/streaming/_messages.py, build_events() constructs a ParsedMessageStopEvent with the accumulated ParsedMessage snapshot. ParsedMessageStopEvent inherits from a Generic, so its schema expects ParsedTextBlock[ResponseFormatT] in message.content. But build() uses construct_type which bypasses validation, stuffing an unparameterized ParsedTextBlock instance into that field. When Pydantic serializes it, it can't match the concrete instance against the generic type parameter and warns.
Only message_stop is affected as other event types don't carry ParsedMessage.content through serialization.
It looks like this may have been introduced in ad56677 and only shows up at serialization time rather than typechecking or validation, likely explaining why this was not caught.
Affected versions: anthropic 0.84.0 through 0.113.0 (latest), all pydantic 2.x versions. Tested:
- anthropic 0.84.0 + pydantic 2.9.2 ✗
- anthropic 0.90.0 + pydantic 2.9.2 ✗
- anthropic 0.100.0 + pydantic 2.9.2 ✗
- anthropic 0.113.0 + pydantic 2.9.2 ✗
- anthropic 0.113.0 + pydantic 2.10.0 ✗
- anthropic 0.113.0 + pydantic 2.11.0 ✗
- anthropic 0.113.0 + pydantic 2.12.0 ✗
- anthropic 0.113.0 + pydantic 2.13.4 ✗
Related: #1175, #1422
When using
client.messages.stream(), callingmodel_dump()on themessage_stopevent producesPydanticSerializationUnexpectedValuewarnings. this happens on every streamed responseRepro:
Root cause:
In
lib/streaming/_messages.py,build_events()constructs aParsedMessageStopEventwith the accumulatedParsedMessagesnapshot.ParsedMessageStopEventinherits from a Generic, so its schema expectsParsedTextBlock[ResponseFormatT]inmessage.content. Butbuild()usesconstruct_typewhich bypasses validation, stuffing an unparameterizedParsedTextBlockinstance into that field. When Pydantic serializes it, it can't match the concrete instance against the generic type parameter and warns.Only
message_stopis affected as other event types don't carryParsedMessage.contentthrough serialization.It looks like this may have been introduced in ad56677 and only shows up at serialization time rather than typechecking or validation, likely explaining why this was not caught.
Affected versions: anthropic 0.84.0 through 0.113.0 (latest), all pydantic 2.x versions. Tested:
Related: #1175, #1422