iflytek/astron-agent · error · ServiceException

CodeEnums.ServiceResponseError

CodeEnums.ServiceResponseError

Error message

<dynamic message from TTS response header>

What it means

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.

Solutions

  1. Read the dynamic `message` in the error — it names the exact iFlytek error; fix the indicated parameter (usually auth, quota, or vcn).
  2. Verify TTS_URL_KEY env var points to the correct iFlytek TTS websocket gateway for your API version.
  3. Check the credentials returned by get_iflytek_open_platform_credentials (app_id, API key, API secret) are valid and not expired.
  4. Retry after backoff if the message indicates quota/concurrency limits; otherwise correct the request parameters (vcn, speed, text length).

Example fix

// before
const vcn = userSelectedVoice; // may be 'unknown_voice'
await smartTts({ text, vcn });
// after
const ALLOWED_VCNS = ['xiaoyan', 'aisjiuxu', 'xiaoqi'];
if (!ALLOWED_VCNS.includes(userSelectedVoice)) userSelectedVoice = 'xiaoyan';
await smartTts({ text, vcn: userSelectedVoice });
Defensive patterns

Strategy: retry

Validate before calling

def tts_request_is_sane(body, creds) -> bool:
    return bool(body.text) and len(body.text) < 8000 and bool(creds.app_id) and body.vcn in KNOWN_VCNS

Try / catch

try:
    resp = await smart_tts_service(body, request)
except ServiceException as e:
    logger.error('TTS upstream error: %s', e.message)
    if 'quota' in e.message or 'concurrent' in e.message:
        await asyncio.sleep(retry_after)
        resp = await smart_tts_service(body, request)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/4fd4271be1eb1d58. Report an issue: GitHub.

Appendix: source

Thrown at core/plugin/aitools/service/smart_tts/smart_tts_service.py:116

    audio_data = bytearray()
    async with WebSocketClient(
        url=url,
        span=span,
        auth="ASE",
        app_id=credentials.app_id,
        api_key=credentials.api_key,
        api_secret=credentials.api_secret,
    ).start() as client:
        await client.send(json.dumps(data))

        async for msg in client.recv():
            message_dict = json.loads(msg)
            code = message_dict.get("header", {}).get("code", 0)
            message = message_dict.get("header", {}).get("message", "")

            if code != 0:
                raise ServiceException.from_error_code(
                    CodeEnums.ServiceResponseError, extra_message=message
                )

            if "payload" in message_dict:
                audio = base64.b64decode(message_dict["payload"]["audio"]["audio"])
                status = message_dict["payload"]["audio"]["status"]

                if status == 2:
                    break

                audio_data.extend(audio)

    if not audio_data:
        raise ServiceException.from_error_code(
            CodeEnums.ServiceResponseError, extra_message="音频数据为空"
        )

    voice_url = await upload_file(str(uuid.uuid4()) + ".MP3", audio_data, span)

View on GitHub (pinned to 5e758547a8)