@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 17ee5b1ac5
Fork 0

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,