{"record":{"id":"c02e021a809c2019","repo":"agentscope-ai/agentscope","slug":"tts-synthesis-failed-no-audio-after-self-max-ret","errorCode":null,"errorMessage":"TTS synthesis failed: no audio after {self.max_retries} attempts","messagePattern":"TTS synthesis failed: no audio after (.+?) attempts","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/agentscope/tts/_dashscope/_realtime_model.py","lineNumber":433,"sourceCode":"                    self._callback.finish_event.wait,\n                )\n\n                if full_text and not self._callback.has_audio_data():\n                    if attempt < self.max_retries - 1:\n                        logger.warning(\n                            \"TTS: no audio received, retrying (%d/%d) in \"\n                            \"%.1fs...\",\n                            attempt + 1,\n                            self.max_retries,\n                            delay,\n                        )\n                        await asyncio.sleep(delay)\n                        await self._reconnect()\n                        unsent = full_text\n                        delay *= 2\n                        continue\n                    self._reset_state()\n                    raise RuntimeError(\n                        f\"TTS synthesis failed: no audio after \"\n                        f\"{self.max_retries} attempts\",\n                    )\n                break\n\n            except WebSocketConnectionClosedException:\n                if attempt < self.max_retries - 1:\n                    logger.warning(\n                        \"TTS WebSocket closed, retrying (%d/%d) in %.1fs...\",\n                        attempt + 1,\n                        self.max_retries,\n                        delay,\n                    )\n                    await asyncio.sleep(delay)\n                    await self._reconnect()\n                    unsent = full_text\n                    delay *= 2\n                else:","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/tts/_dashscope/_realtime_model.py#L415-L451","documentation":"Realtime DashScope TTS synthesis sent the full text but received no audio within the retry loop; after max_retries attempts (with reconnect + exponential backoff) the model resets state and raises. Distinct from a timeout: the flow completed but zero audio bytes arrived.","triggerScenarios":"Calling synthesize() on the realtime model where the websocket accepts text but no binary audio frames come back, on the final retry attempt. Caused by auth failures, unsupported voice/model params, server errors, or a half-dead connection.","commonSituations":"Bad or quota-exhausted DASHSCOPE_API_KEY, mismatched voice for the model, dashscope service incidents, network middleboxes that allow the handshake but drop binary frames.","solutions":["Verify DASHSCOPE_API_KEY validity and quota.","Confirm the voice/model combination is supported.","Inspect websocket close codes/error messages logged near the failure.","Retry at the call site with fresh connect(); if persistent, fall back to non-realtime synthesis.","Report/check dashscope status page for outages."],"exampleFix":"# before\naudio = await model.synthesize(text)\n\n# after\ntry:\n    audio = await model.synthesize(text)\nexcept RuntimeError:\n    await model.disconnect()\n    await model.connect()\n    audio = await model.synthesize(text)","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    audio = await model.synthesize(text)\nexcept RuntimeError as e:\n    if \"no audio after\" in str(e):\n        await model.disconnect()\n        await model.connect()\n        audio = await model.synthesize(text)\n    else:\n        raise","preventionTips":["Verify API key/quota and supported voice before sessions.","Monitor dashscope service status.","Configure a non-realtime fallback TTS model."],"tags":["tts","realtime","dashscope","no-audio","retry-exhausted","websocket"],"backgroundTag":"empty-response-from-stream","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}