{"record":{"id":"45d6c1512bec5f48","repo":"agentscope-ai/agentscope","slug":"agentscope-streaming-model-yielded-no-chunks","errorCode":null,"errorMessage":"\"AgentScope streaming model yielded no chunks.\"","messagePattern":"\"AgentScope streaming model yielded no chunks\\.\"","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/agentscope/middleware/_longterm_memory/_mem0/_agentscope_adapter.py","lineNumber":165,"sourceCode":"async def _await_chat(\n    model: ChatModelBase,\n    messages: list[Msg],\n    tools: list[dict] | None,\n) -> \"ChatResponse\":\n    \"\"\"Call the AgentScope chat model, handling both streaming and\n    non-streaming returns.\"\"\"\n    result = await model(messages, tools=tools)\n    # Streaming model — drain the generator and keep the final chunk,\n    # which carries the complete content per AgentScope's streaming\n    # contract. ``isinstance`` (not ``hasattr``) — Pydantic BaseModel\n    # raises KeyError instead of AttributeError on missing dunder\n    # attrs, which ``hasattr`` does not catch.\n    if isinstance(result, AsyncGenerator):\n        last = None\n        async for chunk in result:\n            last = chunk\n        if last is None:\n            raise RuntimeError(\n                \"AgentScope streaming model yielded no chunks.\",\n            )\n        return last\n    return result\n\n\ndef _convert_messages_to_agentscope(\n    messages: list[dict[str, str]],\n) -> list[Msg]:\n    \"\"\"mem0 hands us OpenAI-style ``[{\"role\", \"content\"}, ...]`` dicts;\n    AgentScope wants ``Msg`` objects.\"\"\"\n    out: list[Msg] = []\n    for m in messages:\n        role = m.get(\"role\")\n        content = m.get(\"content\", \"\")\n        if role == \"system\":\n            out.append(SystemMsg(name=\"system\", content=content))\n        elif role == \"user\":","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/middleware/_longterm_memory/_mem0/_agentscope_adapter.py#L147-L183","documentation":"When the configured ChatModelBase returns an async generator (streaming), the adapter drains it and keeps the last chunk; if the stream yields nothing at all, there is no result to return and a RuntimeError is raised.","triggerScenarios":"Attaching a streaming AgentScope model that immediately completes without emitting chunks (e.g. stub model in tests, provider error that closes the stream silently).","commonSituations":"Unit tests with mocked streaming models that return empty async generators; provider/network edge cases where the stream closes before any chunk arrives.","solutions":["Test the model directly with a real request to confirm it streams chunks","If mocking, make the async generator yield at least one chunk","Check provider API key/quota if real streams terminate empty"],"exampleFix":"// before\nasync def fake_stream(*a, **k):\n    return\n    yield\n// after\nasync def fake_stream(*a, **k):\n    yield ChatResponse(text='ok')","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = llm.generate_response(msgs)\nexcept RuntimeError as e:\n    if 'yielded no chunks' in str(e):\n        result = llm.generate_response(msgs)  # one retry on empty stream\n    else:\n        raise","preventionTips":["Smoke-test streaming models with a real request before wiring them into mem0","Make test mocks yield at least one chunk"],"tags":["agentscope","streaming","empty-response"],"backgroundTag":"empty-stream-response","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}