{"record":{"id":"1b521f3aedf31c65","repo":"run-llama/llama_index","slug":"got-empty-streaming-response-1b521f","errorCode":null,"errorMessage":"Got empty streaming response","messagePattern":"Got empty streaming response","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/agent/workflow/multi_agent_workflow.py","lineNumber":343,"sourceCode":"                raw = (\n                    last_response.raw.model_dump()\n                    if isinstance(last_response.raw, BaseModel)\n                    else last_response.raw\n                )\n                if ctx.is_running:\n                    ctx.write_event_to_stream(\n                        AgentStream(\n                            delta=last_response.delta or \"\",\n                            response=last_response.message.content or \"\",\n                            raw=raw,\n                            current_agent_name=agent.name,\n                            thinking_delta=last_response.additional_kwargs.get(\n                                \"thinking_delta\", None\n                            ),\n                        )\n                    )\n            if last_response is None:\n                raise ValueError(\"Got empty streaming response\")\n            return last_response\n        else:\n            return await agent.llm.achat(llm_input)\n\n    async def _call_tool(\n        self,\n        ctx: Context,\n        tool: AsyncBaseTool,\n        tool_input: dict,\n    ) -> ToolOutput:\n        \"\"\"Call the given tool with the given input.\"\"\"\n        try:\n            if (\n                isinstance(tool, FunctionTool)\n                and tool.requires_context\n                and tool.ctx_param_name is not None\n            ):\n                new_tool_input = {**tool_input}","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/agent/workflow/multi_agent_workflow.py#L325-L361","documentation":"In AgentWorkflow's streaming path (_call_llm with streaming), the loop over chat deltas is expected to produce at least one ChatResponse chunk. If the loop finishes with last_response still None — zero chunks yielded — the workflow raises ValueError('Got empty streaming response') rather than proceeding with nothing.","triggerScenarios":"Running the agent with stream=True against an LLM that returns an empty SSE stream, closes the connection before the first chunk, or whose streaming mode is misconfigured (e.g. stream mode not actually enabled server-side). Also seen with mock/fake LLMs that yield no chunks.","commonSituations":"Switching a provider integration to streaming when the endpoint doesn't support it; a transient network drop right after headers; OpenAI-compatible proxies that return 200 but an empty body; unit tests with stub LLMs that forget to emit deltas.","solutions":["Retry the run — empty streams from hosted LLMs are frequently transient.","Verify streaming works outside AgentWorkflow: `async for c in llm.astream_chat(...)` should yield at least one chunk.","If the endpoint/proxy doesn't support streaming, run without streaming or use a non-streaming-compatible integration.","For test doubles, make the mock astream_chat yield at least one ChatResponse with delta content."],"exampleFix":"# before (mock yields nothing -> ValueError)\nasync def astream_chat(self, messages, **kwargs):\n    return\n    yield\n\n# after\nasync def astream_chat(self, messages, **kwargs):\n    yield ChatResponse(message=ChatMessage(role=\"assistant\", content=\"ok\"), delta=\"ok\")","handlingStrategy":"retry","validationCode":"async def probe_stream(llm, prompt=\"ping\"):\n    n = 0\n    async for _ in llm.astream_chat([ChatMessage(role=\"user\", content=prompt)]):\n        n += 1\n    return n > 0  # false -> streaming will raise 'Got empty streaming response'","typeGuard":null,"tryCatchPattern":"from llama_index.core.workflow.errors import WorkflowRuntimeError\n\nfor attempt in range(3):\n    try:\n        handler = wf.run(user_msg=q, stream=True)\n        async for ev in handler.stream_events():\n            ...\n        result = await handler\n        break\n    except ValueError as e:\n        if \"empty streaming response\" not in str(e) or attempt == 2:\n            raise\n        continue","preventionTips":["Health-check astream_chat on new provider/proxy configurations before wiring into the agent.","Ensure test mocks yield at least one chunk.","Treat a single empty stream as transient; back off and retry before escalating."],"tags":["agent-workflow","streaming","llm","transient"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}