{"record":{"id":"c6351861b0c2c2b8","repo":"run-llama/llama_index","slug":"achat-stream-is-none","errorCode":null,"errorMessage":"achat_stream is None!","messagePattern":"achat_stream is None!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/chat_engine/types.py","lineNumber":352,"sourceCode":"\n                        try:\n                            delta = await asyncio.wait_for(\n                                self.aqueue.get(), timeout=0.1\n                            )\n                        except asyncio.TimeoutError:\n                            # Break only when the stream is done and the queue is empty\n                            if self.is_done and self.aqueue.empty():\n                                break\n                            continue\n                        if delta is not None:\n                            self.unformatted_response += delta\n                            yield delta\n                            yielded_once = True\n                    else:\n                        break\n            else:\n                if self.achat_stream is None:\n                    raise ValueError(\"achat_stream is None!\")\n\n                async for chat_response in self.achat_stream:\n                    self.unformatted_response += chat_response.delta or \"\"\n                    yield chat_response.delta or \"\"\n                    yielded_once = True\n            self.response = self.unformatted_response.strip()\n\n            # edge case where the stream was exhausted before yielding anything\n            if not yielded_once:\n                yield self.response\n        finally:\n            if self.awrite_response_to_history_task:\n                # Make sure that the background task ran to completion, retrieve any exceptions\n                await self.awrite_response_to_history_task\n                self.awrite_response_to_history_task = (\n                    None  # No need to keep the reference to the finished task\n                )\n","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/chat_engine/types.py#L334-L370","documentation":"When a StreamingAgentChatResponse has is_writing_to_memory=False, its async_response_gen coroutine iterates the raw async LLM stream (self.achat_stream) instead of the internal asyncio queue. achat_stream defaults to None, so awaiting/iterating async_response_gen in that state means no async stream was ever attached to the object.","triggerScenarios":"Iterating `async for token in response.async_response_gen()` when is_writing_to_memory=False and achat_stream is None — e.g. the response came from sync stream_chat(), or the object was constructed manually without achat_stream.","commonSituations":"Mixing a sync chat call inside an async web handler and then trying to async-stream it; custom agents that flip is_writing_to_memory=False and forget to attach achat_stream.","solutions":["Obtain the response with await agent.astream_chat(...) so achat_stream is set, then iterate async_response_gen","For sync responses use `for token in response.response_gen`","When constructing manually, pass achat_stream=llm.astream_chat(...) or leave is_writing_to_memory=True so the aqueue path is used"],"exampleFix":"// before\nresponse = agent.stream_chat(\"hi\")\nasync for token in response.async_response_gen():  # ValueError: achat_stream is None!\n    print(token)\n\n// after\nresponse = await agent.astream_chat(\"hi\")\nasync for token in response.async_response_gen():\n    print(token)","handlingStrategy":"validation","validationCode":"if not response.is_writing_to_memory and response.achat_stream is None:\n    raise RuntimeError(\"no aqueue path and no achat_stream; cannot async-iterate\")","typeGuard":"def can_async_iterate(resp) -> bool:\n    return resp.is_writing_to_memory or resp.achat_stream is not None","tryCatchPattern":"try:\n    async for token in response.async_response_gen():\n        print(token, end=\"\")\nexcept ValueError as e:\n    if \"achat_stream is None\" in str(e):\n        for token in response.response_gen:\n            print(token, end=\"\")\n    else:\n        raise","preventionTips":["Use async generators exclusively with responses from astream_chat","Do not flip is_writing_to_memory without attaching the raw achat_stream","Test custom agents with both sync and async entry points to catch mismatches early"],"tags":["streaming","chat-engine","agents","async","sync-async-mismatch"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}