{"record":{"id":"94f18536ac958a3a","repo":"microsoft/semantic-kernel","slug":"polling-timed-out-before-completion","errorCode":null,"errorMessage":"Polling timed out before completion.","messagePattern":"Polling timed out before completion\\.","errorType":"exception","errorClass":"AgentInvokeException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/open_ai/responses_agent_thread_actions.py","lineNumber":219,"sourceCode":"            if response.status in cls.error_message_states:\n                error_message = \"\"\n                if response.error and response.error.message:\n                    error_message = response.error.message\n                incomplete_details = \"\"\n                if response.incomplete_details:\n                    incomplete_details = str(response.incomplete_details.reason)\n                raise AgentInvokeException(\n                    f\"Run failed with status: `{response.status}` for agent `{agent.name}` \"\n                    f\"with error: {error_message} or incomplete details: {incomplete_details}\"\n                )\n\n            try:\n                response = await asyncio.wait_for(\n                    cls._poll_until_completed(agent, response, polling_options or agent.polling_options),\n                    timeout=agent.polling_options.run_polling_timeout.total_seconds(),\n                )\n            except asyncio.TimeoutError:\n                raise AgentInvokeException(\"Polling timed out before completion.\")\n\n            # Type narrowing for subsequent usage\n            assert isinstance(response, Response)  # nosec\n\n            # Extract reasoning content and yield as intermediate message (not visible to user)\n            reasoning_items = cls._get_reasoning_items_from_output(response.output)  # type: ignore\n            if reasoning_items:\n                reasoning_message = ChatMessageContent(\n                    role=AuthorRole.ASSISTANT,\n                    items=cast(list[CMC_ITEM_TYPES], reasoning_items),\n                    ai_model_id=agent.ai_model_id,\n                    metadata=cls._get_metadata_from_response(response),\n                    name=agent.name,\n                )\n                yield False, reasoning_message\n\n            # Check if tool calls are required\n            function_calls = cls._get_tool_calls_from_output(response.output)  # type: ignore","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/open_ai/responses_agent_thread_actions.py#L201-L237","documentation":"Raised as an AgentInvokeException when the polling loop that waits for a non-streaming OpenAI Responses run to reach \"completed\" exceeds agent.polling_options.run_polling_timeout. The Responses API returns runs that are processed server-side, so Semantic Kernel polls responses.retrieve until status == \"completed\"; if that does not happen within the configured deadline, this fires.","triggerScenarios":"asyncio.wait_for around _poll_until_completed (which loops calling agent.client.responses.retrieve until status == \"completed\") hits the timeout configured at agent.polling_options.run_polling_timeout. Happens on long-running runs (complex tool use, large outputs), slow backend, or a polling interval/time budget misconfiguration in RunPollingOptions.","commonSituations":"Default run_polling_timeout too short for heavy multi-step tool-calling runs; network latency to OpenAI inflating each retrieve round-trip; backend slowness during peak load; RunPollingOptions misconfigured with a tiny timeout; runs that legitimately need many tool invocations.","solutions":["Increase agent.polling_options.run_polling_timeout to a larger timedelta.","Tune polling_options polling interval/strategy via RunPollingOptions so polls are neither too sparse nor too aggressive.","Reduce the run's complexity (fewer tools, smaller context) so it completes faster.","Verify network connectivity/latency to the OpenAI endpoint; a slow link makes each retrieve poll expensive.","If using Azure, check the deployment region/provisioned throughput for slowness."],"exampleFix":"# before\nagent = OpenAIResponsesAgent(\n    ai_model_id=\"gpt-4o\",\n    client=client,\n    instructions=\"...\",\n)\n# after - give long tool-using runs a larger polling budget\nfrom semantic_kernel.agents.open_ai import RunPollingOptions\nagent.polling_options = RunPollingOptions(run_polling_timeout=timedelta(minutes=5))","handlingStrategy":"retry","validationCode":"# Confirm the polling timeout fits the worst-case run before invoking:\nfrom datetime import timedelta\nif agent.polling_options.run_polling_timeout < timedelta(seconds=30):\n    agent.polling_options.run_polling_timeout = timedelta(minutes=3)","typeGuard":null,"tryCatchPattern":"from semantic_kernel.exceptions import AgentInvokeException\nattempt = 0\nwhile True:\n    try:\n        async for is_final, msg in agent.invoke(thread=thread):\n            ...\n        break\n    except AgentInvokeException as ex:\n        if \"Polling timed out\" not in str(ex) or attempt >= 2:\n            raise\n        attempt += 1  # retry after widening the budget\n        agent.polling_options.run_polling_timeout *= 2","preventionTips":["Size run_polling_timeout to the slowest expected run (multi-tool, large output).","Monitor average run completion times and adjust the budget accordingly.","Keep the polling interval reasonable so retrieve calls are not too sparse."],"tags":["openai-responses","agent","timeout","polling"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}