microsoft/semantic-kernel · error · ServiceInvalidResponseError
Expected an AsyncStream[ChatCompletionChunk] response.
Error message
Expected an AsyncStream[ChatCompletionChunk] response.
What it means
Raised inside the streaming chat-completion generator (_complete_chat_stream) after the OpenAI client returns a response object that is not an openai.AsyncStream. The method unconditionally sets stream=True on the settings and expects the SDK to yield ChatCompletionChunk objects; a non-stream response indicates the request was misconfigured or the SDK version is incompatible.
Source
Thrown at python/semantic_kernel/connectors/ai/open_ai/services/open_ai_chat_completion_base.py:112
@trace_streaming_chat_completion(MODEL_PROVIDER_NAME)
async def _inner_get_streaming_chat_message_contents(
self,
chat_history: "ChatHistory",
settings: "PromptExecutionSettings",
function_invoke_attempt: int = 0,
) -> AsyncGenerator[list["StreamingChatMessageContent"], Any]:
if not isinstance(settings, OpenAIChatPromptExecutionSettings):
settings = self.get_prompt_execution_settings_from_settings(settings)
assert isinstance(settings, OpenAIChatPromptExecutionSettings) # nosec
settings.stream = True
settings.stream_options = {"include_usage": True}
settings.messages = self._prepare_chat_history_for_request(chat_history)
settings.ai_model_id = settings.ai_model_id or self.ai_model_id
response = await self._send_request(settings)
if not isinstance(response, AsyncStream):
raise ServiceInvalidResponseError("Expected an AsyncStream[ChatCompletionChunk] response.")
async for chunk in response:
if len(chunk.choices) == 0 and chunk.usage is None:
continue
assert isinstance(chunk, ChatCompletionChunk) # nosec
chunk_metadata = self._get_metadata_from_streaming_chat_response(chunk)
if (not chunk.choices or len(chunk.choices) == 0) and chunk.usage is not None:
# Usage is contained in the last chunk where the choices are empty
# We are duplicating the usage metadata to all the choices in the response
yield [
StreamingChatMessageContent(
role=AuthorRole.ASSISTANT,
content="",
choice_index=i,
inner_content=chunk,
ai_model_id=settings.ai_model_id,
metadata=chunk_metadata,
function_invoke_attempt=function_invoke_attempt,View on GitHub (pinned to c028a0c7dc)
Solutions
- Ensure settings.stream is not being overridden to False before or after the streaming call path is entered
- Verify the openai package version matches the one required by your semantic-kernel version (check pyproject.toml or requirements.txt)
- If using a custom client, confirm it returns an AsyncStream[ChatCompletionChunk] when stream=True is passed
- Avoid injecting a pre-configured client that wraps or intercepts the create() call in a way that changes the return type
Example fix
# before — mock returns a non-stream object
mock_client.chat.completions.create.return_value = ChatCompletion(...)
# after — mock returns an AsyncStream
async def _fake_stream():
yield ChatCompletionChunk(...)
mock_client.chat.completions.create.return_value = _fake_stream() Defensive patterns
Strategy: try-catch
Type guard
from openai import AsyncStream
from openai.types.chat import ChatCompletionChunk
def is_valid_stream_response(response) -> bool:
return isinstance(response, AsyncStream) Try / catch
from semantic_kernel.exceptions.service_exceptions import ServiceInvalidResponseError
try:
async for chunk in service._complete_chat_stream(...):
...
except ServiceInvalidResponseError as e:
logger.error('Streaming response was not an AsyncStream; falling back to non-streaming')
response = await service.get_chat_message_content(...) Prevention
- Pin the openai SDK version to the one tested by your semantic-kernel release
- In tests, always mock streaming endpoints with real AsyncStream-compatible objects
When it happens
Trigger: Calling the streaming completion path (get_streaming_chat_message_content or _complete_chat_stream) when the underlying OpenAI SDK client returns a non-streamed ChatCompletion object — e.g., because stream was overridden elsewhere, a custom client wrapper stripped streaming, or the openai package version returns a different response type.
Common situations: Using a mocked or custom AsyncOpenAI client in tests that returns a ChatCompletion instead of an AsyncStream; upgrading/downgrading the openai Python package to a version with a changed streaming contract; a proxy or gateway that buffers and de-chunks the response.
Related errors
- Failed to get a response from the chat completion service.
- Agent Failure - Run not created for thread: ${threadId}
- The provided reasoning effort '{textEffortLevel}' is not sup
- The provided reasoning effort '{effortLevelObject.GetType()}
- The provided web search options '{executionSettings.WebSearc
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/b9039648f816ce47.
Report an issue: GitHub.