{"record":{"id":"4fd4271be1eb1d58","repo":"iflytek/astron-agent","slug":"codeenums-serviceresponseerror","errorCode":"CodeEnums.ServiceResponseError","errorMessage":"<dynamic message from TTS response header>","messagePattern":"<dynamic message from TTS response header>","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"core/plugin/aitools/service/smart_tts/smart_tts_service.py","lineNumber":116,"sourceCode":"\n    audio_data = bytearray()\n    async with WebSocketClient(\n        url=url,\n        span=span,\n        auth=\"ASE\",\n        app_id=credentials.app_id,\n        api_key=credentials.api_key,\n        api_secret=credentials.api_secret,\n    ).start() as client:\n        await client.send(json.dumps(data))\n\n        async for msg in client.recv():\n            message_dict = json.loads(msg)\n            code = message_dict.get(\"header\", {}).get(\"code\", 0)\n            message = message_dict.get(\"header\", {}).get(\"message\", \"\")\n\n            if code != 0:\n                raise ServiceException.from_error_code(\n                    CodeEnums.ServiceResponseError, extra_message=message\n                )\n\n            if \"payload\" in message_dict:\n                audio = base64.b64decode(message_dict[\"payload\"][\"audio\"][\"audio\"])\n                status = message_dict[\"payload\"][\"audio\"][\"status\"]\n\n                if status == 2:\n                    break\n\n                audio_data.extend(audio)\n\n    if not audio_data:\n        raise ServiceException.from_error_code(\n            CodeEnums.ServiceResponseError, extra_message=\"音频数据为空\"\n        )\n\n    voice_url = await upload_file(str(uuid.uuid4()) + \".MP3\", audio_data, span)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/plugin/aitools/service/smart_tts/smart_tts_service.py#L98-L134","documentation":"During streaming TTS synthesis, each WebSocket message from the iFlytek TTS endpoint carries a header with a return `code`. A non-zero code means the TTS backend rejected or failed the synthesis request; the service re-raises it as a ServiceResponseError with the backend's own `message` from the response header. This is an upstream API error surfaced verbatim to the caller.","triggerScenarios":"The async loop `async for msg in client.recv()` receives a frame whose header code != 0 — e.g. invalid/expired iFlytek Open Platform credentials (app_id/API key), quota or concurrency limits exhausted, invalid voice name (vcn) or audio parameters, or malformed text causing backend rejection.","commonSituations":"TTS_URL_KEY points to a wrong or stale gateway URL; credentials configured via get_iflytek_open_platform_credentials are wrong, rotated, or expired; free-tier daily quota or concurrent-connection limit exceeded; unsupported vcn value passed in the request.","solutions":["Read the dynamic `message` in the error — it names the exact iFlytek error; fix the indicated parameter (usually auth, quota, or vcn).","Verify TTS_URL_KEY env var points to the correct iFlytek TTS websocket gateway for your API version.","Check the credentials returned by get_iflytek_open_platform_credentials (app_id, API key, API secret) are valid and not expired.","Retry after backoff if the message indicates quota/concurrency limits; otherwise correct the request parameters (vcn, speed, text length)."],"exampleFix":"// before\nconst vcn = userSelectedVoice; // may be 'unknown_voice'\nawait smartTts({ text, vcn });\n// after\nconst ALLOWED_VCNS = ['xiaoyan', 'aisjiuxu', 'xiaoqi'];\nif (!ALLOWED_VCNS.includes(userSelectedVoice)) userSelectedVoice = 'xiaoyan';\nawait smartTts({ text, vcn: userSelectedVoice });","handlingStrategy":"retry","validationCode":"def tts_request_is_sane(body, creds) -> bool:\n    return bool(body.text) and len(body.text) < 8000 and bool(creds.app_id) and body.vcn in KNOWN_VCNS","typeGuard":null,"tryCatchPattern":"try:\n    resp = await smart_tts_service(body, request)\nexcept ServiceException as e:\n    logger.error('TTS upstream error: %s', e.message)\n    if 'quota' in e.message or 'concurrent' in e.message:\n        await asyncio.sleep(retry_after)\n        resp = await smart_tts_service(body, request)\n    else:\n        raise","preventionTips":["Monitor iFlytek quota and concurrency usage; alert before exhaustion.","Validate vcn and speed against known-good values before calling.","Keep TTS_URL_KEY and credentials in checked configuration with startup validation.","Surface the upstream header message to logs on every failure for fast diagnosis."],"tags":["tts","upstream-api","websocket"],"backgroundTag":"api-error-response","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}