decolua/9router · error
Failed to parse Bing token
Error message
Failed to parse Bing token
What it means
After fetching the Bing translator page successfully, getToken() regex-extracts params_AbusePreventionHelper = [key, token, ...] from the HTML. If the pattern is absent it throws 'Failed to parse Bing token'. This means Bing served the page but did not embed the expected token — usually a page-structure change or a bot-detection interstitial.
Source
Thrown at open-sse/handlers/ttsProviders/edgeTts.js:23
const REFRESH_MS = 5 * 60 * 1000; // token TTL ~1h, refresh early
const VOICES_TTL = 24 * 60 * 60 * 1000;
const cache = { token: null, tokenTime: 0 };
let _voicesCache = null;
let _voicesCacheTime = 0;
async function getToken() {
const now = Date.now();
if (cache.token && now - cache.tokenTime < REFRESH_MS) return cache.token;
const res = await fetch("https://www.bing.com/translator", {
headers: { "User-Agent": UA, "Accept-Language": "vi,en-US;q=0.9,en;q=0.8" },
});
if (!res.ok) throw new Error(`Bing translator fetch failed: ${res.status}`);
const rawCookies = res.headers.getSetCookie?.() || [];
const cookie = rawCookies.map((c) => c.split(";")[0]).join("; ");
const html = await res.text();
const match = html.match(/params_AbusePreventionHelper\s*=\s*\[([^,]+),([^,]+),/);
if (!match) throw new Error("Failed to parse Bing token");
cache.token = { key: match[1], token: match[2].replace(/"/g, ""), cookie };
cache.tokenTime = now;
return cache.token;
}
async function ttsRequest(text, voiceId, token) {
const parts = voiceId.split("-");
const xmlLang = parts.slice(0, 2).join("-");
const gender = voiceId.toLowerCase().includes("male") ? "Male" : "Female";
const ssml = `<speak version='1.0' xml:lang='${xmlLang}'><voice xml:lang='${xmlLang}' xml:gender='${gender}' name='${voiceId}'><prosody rate='0.00%'>${text}</prosody></voice></speak>`;
const body = new URLSearchParams();
body.append("ssml", ssml);
body.append("token", token.token);
body.append("key", token.key);
return fetch("https://www.bing.com/tfettts?isVertical=1&&IG=1&IID=translator.5023&SFX=1", {
method: "POST",
body: body.toString(),
headers: {View on GitHub (pinned to 90b52e06ff)
Solutions
- Update the regex in open-sse/handlers/ttsProviders/edgeTts.js to match the current page structure — fetch https://www.bing.com/translator and inspect where the token now lives
- Check whether the response is a redirect/consent page; follow redirects or add the required cookies
- Use a different User-Agent or add Accept-Language headers matching a region that still serves the token
- Pin to a known-good mirror/proxy of the translator page, or switch to another TTS provider
- Track the edge-tts community (e.g. edge-tts Python package issues) — when this breaks it is usually upstream-wide and fixed by matching their updated approach
Defensive patterns
Strategy: fallback
Validate before calling
const html = await (await fetch("https://www.bing.com/translator")).text();
if (!/params_AbusePreventionHelper/.test(html)) console.warn("Bing token missing from page — edgeTts parser likely outdated"); Try / catch
try {
const audio = await edgeTts.synthesize(text, voice);
} catch (e) {
if (e.message === "Failed to parse Bing token") return fallbackTts.synthesize(text, voice);
throw e;
} Prevention
- Pin/monitor the upstream edge-tts project for page-structure break reports
- Keep a non-scraping TTS provider as fallback for production workloads
- Add a startup health check that probes the Bing token once and alerts on parse failure
- Avoid tight loops of synthesis that trigger Bing bot detection
When it happens
Trigger: Bing changes the HTML template or renames params_AbusePreventionHelper; Bing returns a CAPTCHA/consent/redirect page instead of the translator page; the request was served a regional variant lacking the token script; the regex (which requires two comma-separated fields) no longer matches the embedded array.
Common situations: Bing deployed an update (Edge TTS token scraping breaks community-wide when this happens); running from a region where bing.com redirects to a consent page; datacenter IP served a challenge page with 200 status; stale cached HTML from a proxy.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Bing translator fetch failed: ${res.status}
- Edge TTS voices fetch failed: ${res.status}
- Failed to parse Google token
- Upstream returned empty audio
- Upstream error (${res.status})
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/e0a24c1351369b12.
Report an issue: GitHub.