A high-throughput and memory-efficient inference and serving engine for LLMs
[Bugfix] Set type/role explicitly in streaming message_start event (#45376)
Signed-off-by: Wayne Chiu <waynehacking8@gmail.com>
WEI CHENG CHIU committed
Jun 13, 2026 at 09:40 UTC
17ee5b1ac5dd61fa89bc4321ef54b0a790a45db3
2 files changed
+43
tests/entrypoints/anthropic/test_anthropic_messages_conversion.py
+36
@@ -996,3 +996,39 @@ class TestMessageStreamConverterToolUseContentBuffering:
996
assert "text" in block_starts
997
998
assert events[-1][0] == "message_stop"
999
+
1000
+
1001
+class TestMessageStartIncludesTypeAndRole:
1002
+ """Regression test for issue #45367: the streaming message_start event is
1003
+ serialized with exclude_unset=True, which silently dropped the
1004
+ default-valued ``type``/``role`` fields of the nested message object.
1005
+ Strict Anthropic SDK clients (e.g. Claude Code) validate
1006
+ ``message_start.message.type``/``role`` and reject the whole stream when
1007
+ they are missing.
1008
+ """
1009
+
1010
+ @pytest.mark.asyncio
1011
+ async def test_message_start_contains_message_type_and_role(self):
1012
+ async def sse_input():
1013
+ yield _make_stream_chunk(
1014
+ delta=DeltaMessage(content="Hello"),
1015
+ usage=UsageInfo(
1016
+ prompt_tokens=20,
1017
+ total_tokens=20,
1018
+ completion_tokens=0,
1019
+ ),
1020
+ )
1021
+ yield _make_stream_chunk(finish_reason="stop")
1022
+ yield "data: [DONE]"
1023
+
1024
+ converter = _make_stream_converter()
1025
+ output = []
1026
+ async for event in converter.message_stream_converter(sse_input()):
1027
+ output.append(event)
1028
+
1029
+ events = _parse_sse_events(output)
1030
+
1031
+ assert events[0][0] == "message_start"
1032
+ message = events[0][1]["message"]
1033
+ assert message["type"] == "message"
1034
+ assert message["role"] == "assistant"
vllm/entrypoints/anthropic/serving.py
+7
@@ -678,6 +678,13 @@ class AnthropicServingMessages(OpenAIServingChat):
678
type="message_start",
679
message=AnthropicMessagesResponse(
680
id=origin_chunk.id,
681
+ # Set explicitly: this event is serialized
682
+ # with exclude_unset=True, which drops
683
+ # default-valued fields, while strict
684
+ # Anthropic SDK clients require
685
+ # message.type/role (issue #45367).
686
+ type="message",
687
+ role="assistant",
688
content=[],
689
model=origin_chunk.model,
690
stop_reason=None,