{"record":{"id":"be265a1ce932d537","repo":"decolua/9router","slug":"edge-tts-voices-fetch-failed-res-status","errorCode":null,"errorMessage":"Edge TTS voices fetch failed: ${res.status}","messagePattern":"Edge TTS voices fetch failed: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/handlers/ttsProviders/edgeTts.js","lineNumber":59,"sourceCode":"    headers: {\n      \"Content-Type\": \"application/x-www-form-urlencoded\",\n      \"Accept\": \"*/*\",\n      \"Origin\": \"https://www.bing.com\",\n      \"Referer\": \"https://www.bing.com/translator\",\n      \"User-Agent\": UA,\n      ...(token.cookie ? { \"Cookie\": token.cookie } : {}),\n    },\n  });\n}\n\nexport async function fetchEdgeTtsVoices() {\n  const now = Date.now();\n  if (_voicesCache && now - _voicesCacheTime < VOICES_TTL) return _voicesCache;\n  const res = await fetch(\n    \"https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=6A5AA1D4EAFF4E9FB37E23D68491D6F4\",\n    { headers: { \"User-Agent\": UA } }\n  );\n  if (!res.ok) throw new Error(`Edge TTS voices fetch failed: ${res.status}`);\n  const voices = await res.json();\n  _voicesCache = voices;\n  _voicesCacheTime = now;\n  return voices;\n}\n\nexport default {\n  noAuth: true,\n  async synthesize(text, model) {\n    const voiceId = model || \"vi-VN-HoaiMyNeural\";\n    let token = await getToken();\n    let res = await ttsRequest(text, voiceId, token);\n\n    // 429/403: invalidate cache and retry once\n    if (res.status === 429 || res.status === 403) {\n      cache.token = null;\n      cache.tokenTime = 0;\n      token = await getToken();","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/ttsProviders/edgeTts.js#L41-L77","documentation":"fetchEdgeTtsVoices() retrieves the Edge TTS voice catalog from speech.platform.bing.com using a hardcoded trustedclienttoken, caching results for VOICES_TTL. A non-2xx response throws 'Edge TTS voices fetch failed: <status>'. This is a catalog-only call (voice listing); synthesis uses getToken() instead, but voice listing features will fail with this error.","triggerScenarios":"The voices/list endpoint returns 401 (trusted client token revoked/rotated by Microsoft), 403 (IP/UA blocked), 429 (rate limited from repeated listing), or 5xx (Microsoft service issue).","commonSituations":"Microsoft rotated the trustedclienttoken (historically happens, breaking all edge-tts clients); datacenter IP blocked by the speech endpoint; dashboard voice-picker called too frequently and rate limited; regional outage.","solutions":["If 401, check the edge-tts community for the new trustedclienttoken and update the hardcoded value in open-sse/handlers/ttsProviders/edgeTts.js","If 429, wait for the cache TTL or reset window; the function already caches voices for VOICES_TTL so avoid busting it","Verify connectivity: curl the voices/list URL from the host to see the actual status/body","Retry with backoff for 5xx/transient failures","Fall back to a static/cached voice list so the UI works offline"],"exampleFix":"// before\nconst voices = await fetchEdgeTtsVoices();\n// after\nlet voices;\ntry {\n  voices = await fetchEdgeTtsVoices();\n} catch (e) {\n  voices = DEFAULT_EDGE_VOICES; // static fallback list\n  console.warn(\"Edge TTS voices fetch failed, using cached list:\", e.message);\n}","handlingStrategy":"fallback","validationCode":"const probe = await fetch(VOICES_URL).catch(() => null);\nif (!probe || !probe.ok) console.warn(\"Edge TTS voice catalog unreachable — status \" + (probe?.status ?? \"network-error\"));","typeGuard":"function isVoicesFetchError(e) { return e instanceof Error && e.message.startsWith(\"Edge TTS voices fetch failed\"); }","tryCatchPattern":"try {\n  const voices = await fetchEdgeTtsVoices();\n} catch (e) {\n  const voices = CACHED_VOICES ?? []; // serve stale/static list\n  console.warn(\"Voice catalog unavailable:\", e.message);\n}","preventionTips":["Respect the VOICES_TTL cache — do not bypass it with repeated direct calls","Watch for Microsoft rotating the trustedclienttoken and update it promptly","Serve a bundled static voice list when the live catalog is unreachable","Retry with backoff on 5xx rather than hammering the endpoint"],"tags":["tts","edge-tts","network","http-error","token"],"backgroundTag":"upstream-http-error","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}