{"record":{"id":"e1d381c5204f666d","repo":"microsoft/semantic-kernel","slug":"invalid-response-type-from-ollama-chat-completion","errorCode":null,"errorMessage":"Invalid response type from Ollama chat completion. Expected Mapping or ChatResponse but got {type(response_object)}.","messagePattern":"Invalid response type from Ollama chat completion\\. Expected Mapping or ChatResponse but got (.+?)\\.","errorType":"exception","errorClass":"ServiceInvalidResponseError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/ai/ollama/services/ollama_chat_completion.py","lineNumber":172,"sourceCode":"    ) -> list[\"ChatMessageContent\"]:\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=False,\n            **settings.prepare_settings_dict(),\n        )\n\n        if isinstance(response_object, ChatResponse):\n            return [self._create_chat_message_content_from_chat_response(response_object)]\n        if isinstance(response_object, Mapping):\n            return [self._create_chat_message_content(response_object)]\n        raise ServiceInvalidResponseError(\n            \"Invalid response type from Ollama chat completion. \"\n            f\"Expected Mapping or ChatResponse but got {type(response_object)}.\"\n        )\n\n    @override\n    @trace_streaming_chat_completion(OllamaBase.MODEL_PROVIDER_NAME)\n    async def _inner_get_streaming_chat_message_contents(\n        self,\n        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","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/ai/ollama/services/ollama_chat_completion.py#L154-L190","documentation":"Raised as ServiceInvalidResponseError when the object returned by `self.client.chat(..., stream=False)` is neither a `ChatResponse` (typed ollama SDK) nor a `Mapping` (raw dict, older/compat path). The connector can only build a ChatMessageContent from one of those two shapes, so anything else is treated as a protocol break.","triggerScenarios":"The installed `ollama` python package returns an unexpected response type from `client.chat` - e.g. a major SDK version change that returns a different class, a pydantic model that is not a Mapping, or a custom client wrapper returning a foreign object.","commonSituations":"Upgrading the ollama python SDK to a version whose ChatResponse lives elsewhere / has a different class; using a mocked/fake client in tests that returns a plain object; an ollama server version that returns an unexpected JSON shape that the SDK maps to a new type.","solutions":["Pin the ollama python package to the version semantic_kernel's connector expects (check the connector's requirements).","If passing a custom client, ensure its `.chat(...)` returns either an ollama ChatResponse or a dict/Mapping.","In tests, return ollama.ChatResponse(...) or a dict matching the documented schema."],"exampleFix":"# before (custom test client)\nclass FakeClient:\n    async def chat(self, **kw):\n        return MyCustomObject()\n\n# after\nfrom ollama import ChatResponse\nclass FakeClient:\n    async def chat(self, **kw):\n        return ChatResponse.model_validate({'message': {'role':'assistant','content':'hi'}})","handlingStrategy":"type-guard","validationCode":"# Validate the client returns the expected shape in a smoke test\nresp = await svc.client.chat(model=svc.ai_model_id, messages=[{'role':'user','content':'hi'}], stream=False)\nfrom ollama import ChatResponse\nfrom collections.abc import Mapping\nassert isinstance(resp, (ChatResponse, Mapping)), f'unexpected type {type(resp)}'","typeGuard":"from ollama import ChatResponse\nfrom collections.abc import Mapping\n\ndef is_valid_ollama_chat_resp(obj) -> bool:\n    return isinstance(obj, (ChatResponse, Mapping))","tryCatchPattern":"from semantic_kernel.exceptions import ServiceInvalidResponseError\ntry:\n    resp = await svc.get_chat_message_contents(chat_history, settings)\nexcept ServiceInvalidResponseError as e:\n    if 'Invalid response type from Ollama chat' in str(e):\n        raise RuntimeError('ollama SDK/server version mismatch - pin the expected package version') from e\n    raise","preventionTips":["Pin the ollama python package to the version the connector supports.","If supplying a custom client, return ollama.ChatResponse or a dict from .chat().","Add a smoke test that asserts the response type before relying on the connector."],"tags":["ollama","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"}