decolua/9router · error · Error
Google TTS failed: ${res.status}
Error message
Google TTS failed: ${res.status} What it means
The synthesize function POSTs an RPC batchexecute request to translate.google.com to get MP3 audio. Non-2xx responses throw this error with the upstream HTTP status. Since this is an undocumented internal Google RPC endpoint, non-200s usually mean the request/token is stale or blocked.
Source
Thrown at open-sse/handlers/ttsProviders/googleTts.js:47
const reqId = (++_idx * 100000) + Math.floor(1000 + Math.random() * 9000);
const query = new URLSearchParams({
rpcids: rpcId,
"f.sid": token["f.sid"],
bl: token.bl,
hl: lang,
"soc-app": 1, "soc-platform": 1, "soc-device": 1,
_reqid: reqId,
rt: "c",
});
const payload = [cleanText, lang, null, "undefined", [0]];
const body = new URLSearchParams();
body.append("f.req", JSON.stringify([[[rpcId, JSON.stringify(payload), null, "generic"]]]));
const res = await fetch(`https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?${query}`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded", "Referer": "https://translate.google.com/" },
body: body.toString(),
});
if (!res.ok) throw new Error(`Google TTS failed: ${res.status}`);
const data = await res.text();
const split = JSON.parse(data.split("\n")[3]);
const base64 = JSON.parse(split[0][2])[0];
if (!base64 || base64.length < 100) throw new Error("Google TTS returned empty audio");
return { base64, format: "mp3" };
},
};
View on GitHub (pinned to 90b52e06ff)
Solutions
- Invalidate the token cache and refetch (fix the scraper/token) so batchexecute runs with fresh f.sid/bl
- Confirm headers: `Content-Type: application/x-www-form-urlencoded` and `Referer: https://translate.google.com/` must be present
- Check the status code in the message: 429 → backoff/IP rotation; 400 → inspect the f.req payload against current schema
- Switch to an official TTS provider or maintained google-tts-api library for reliability
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
try { return await googleTts.synthesize(text); } catch (e) { const m = e.message.match(/Google TTS failed: (\d+)/); if (m && (m[1] === '429' || m[1].startsWith('5'))) { await sleep(expBackoff()); return retryOnce(); } throw e; } Prevention
- Keep Referer and Content-Type headers exactly as the internal RPC expects
- Refresh f.sid/bl tokens when this fires instead of retrying with the same stale token
- Chunk long text to stay within batchexecute limits
When it happens
Trigger: batchexecute returns 4xx/5xx: expired/invalid `f.sid`/`bl` token in the query, missing/bad Referer, rate limiting (429), or Google blocking the internal RPC for the client IP.
Common situations: Long-lived process using a token scraped hours ago that Google invalidated; datacenter IP blocked; malformed f.req after a payload schema change (surfacing as 400).
Related errors
- MiniMax TTS error (${res.status})
- Google translate fetch failed: ${res.status}
- Failed to fetch image: ${res.status}
- Upstream returned empty audio
- Upstream error (${res.status})
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/ecb9086a2d9250c2.
Report an issue: GitHub.