{"record":{"id":"d2c8560415551443","repo":"microsoft/semantic-kernel","slug":"invalid-response-type-from-ollama-streaming-chat-c","errorCode":null,"errorMessage":"Invalid response type from Ollama streaming chat completion. Expected AsyncIterator but got {type(response_object)}.","messagePattern":"Invalid response type from Ollama streaming chat completion\\. Expected AsyncIterator but got (.+?)\\.","errorType":"exception","errorClass":"ServiceInvalidResponseError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/ai/ollama/services/ollama_chat_completion.py","lineNumber":199,"sourceCode":"        chat_history: \"ChatHistory\",\n        settings: \"PromptExecutionSettings\",\n        function_invoke_attempt: int = 0,\n    ) -> AsyncGenerator[list[\"StreamingChatMessageContent\"], Any]:\n        if not isinstance(settings, OllamaChatPromptExecutionSettings):\n            settings = self.get_prompt_execution_settings_from_settings(settings)\n        assert isinstance(settings, OllamaChatPromptExecutionSettings)  # nosec\n\n        prepared_chat_history = self._prepare_chat_history_for_request(chat_history)\n\n        response_object = await self.client.chat(\n            model=self.ai_model_id,\n            messages=prepared_chat_history,\n            stream=True,\n            **settings.prepare_settings_dict(),\n        )\n\n        if not isinstance(response_object, AsyncIterator):\n            raise ServiceInvalidResponseError(\n                \"Invalid response type from Ollama streaming chat completion. \"\n                f\"Expected AsyncIterator but got {type(response_object)}.\"\n            )\n\n        async for part in response_object:\n            if isinstance(part, ChatResponse):\n                yield [self._create_streaming_chat_message_content_from_chat_response(part, function_invoke_attempt)]\n                continue\n            if isinstance(part, Mapping):\n                yield [self._create_streaming_chat_message_content(part, function_invoke_attempt)]\n                continue\n            raise ServiceInvalidResponseError(\n                \"Invalid response type from Ollama streaming chat completion. \"\n                f\"Expected mapping or ChatResponse but got {type(part)}.\"\n            )\n\n    # endregion\n","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/ai/ollama/services/ollama_chat_completion.py#L181-L217","documentation":"Raised as ServiceInvalidResponseError when the streaming call `self.client.chat(..., stream=True)` returns something that is NOT an `AsyncIterator`. The streaming path must iterate parts asynchronously; a non-iterable result means the client/server did not enter streaming mode as expected.","triggerScenarios":"The ollama client returns a single ChatResponse (non-streaming) despite stream=True - e.g. a custom client ignoring the stream flag, an SDK version that changed streaming behavior, or a server/proxy that degrades streaming into a single response.","commonSituations":"A mock client whose `.chat()` returns a coroutine resolving to a dict instead of an async iterator; an ollama reverse proxy that buffers and returns one object; SDK version mismatch changing the streaming return type.","solutions":["If using a custom client, make `.chat(..., stream=True)` return an AsyncIterator yielding parts.","Pin/align the ollama python SDK version with the connector's expectations.","If the server cannot stream, call the non-streaming path (`stream=False`) instead of the streaming kernel method.","In tests, return an async generator: `async def chat(...): yield ChatResponse(...)`."],"exampleFix":"# before (fake client returns a plain dict)\nasync def chat(self, **kw):\n    return {'message': {...}}\n\n# after - streaming returns an async iterator\nasync def chat(self, **kw):\n    assert kw.get('stream')\n    yield ChatResponse.model_validate({'message': {'role':'assistant','content':'hi'}})","handlingStrategy":"type-guard","validationCode":"# Smoke-test streaming returns an async iterator\nresp = await svc.client.chat(model=svc.ai_model_id, messages=[{'role':'user','content':'hi'}], stream=True)\nfrom collections.abc import AsyncIterator\nassert isinstance(resp, AsyncIterator), f'stream=True must yield AsyncIterator, got {type(resp)}'","typeGuard":"from collections.abc import AsyncIterator\n\ndef is_ollama_stream_iter(obj) -> bool:\n    return isinstance(obj, AsyncIterator)","tryCatchPattern":"from semantic_kernel.exceptions import ServiceInvalidResponseError\ntry:\n    async for chunk in svc._inner_get_streaming_chat_message_contents(chat_history, settings):\n        ...\nexcept ServiceInvalidResponseError as e:\n    if 'Expected AsyncIterator' in str(e):\n        raise RuntimeError('client did not stream; use non-streaming path or fix client') from e\n    raise","preventionTips":["Custom/mock clients must return an AsyncIterator from .chat(stream=True).","If the server cannot stream, call the non-streaming method instead.","Pin the ollama SDK version matching the connector."],"tags":["ollama","streaming","chat-completion","response-shape","sdk-version","service-invalid-response-error"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}