decolua/9router · error · Error

Google TTS returned empty audio

Error message

Google TTS returned empty audio

What it means

A 200 response from batchexecute is parsed line-wise: `data.split("\n")[3]` → JSON → `[0][2]` → JSON → first element must be a base64 string of at least 100 chars. If the audio payload is missing, empty, or suspiciously short, this error is thrown. It means Google responded OK but without usable audio.

Source

Thrown at open-sse/handlers/ttsProviders/googleTts.js:51

      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

  1. Validate `text` is non-empty before calling synthesize and keep it under the length limit (chunk long text)
  2. Log the raw response to check whether line 3 / [0][2] still holds the audio array; update the parse indices if the layout changed
  3. Check the in-body status/error inside the parsed split payload — batchexecute often reports errors with HTTP 200
  4. Fall back to another TTS provider (the handler layer supports per-provider fallback)

Example fix

// before
if (!base64 || base64.length < 100) throw new Error('Google TTS returned empty audio');
// after
if (!base64 || base64.length < 100) {
  throw new Error('Google TTS returned empty audio; raw=' + data.slice(0, 300));
}
Defensive patterns

Strategy: validation

Validate before calling

if (!text?.trim()) throw new Error('text required for Google TTS');
if (text.length > 200) text = text.slice(0, 200); // or chunk

Type guard

const parsed = JSON.parse(data.split('\n')[3]); const okShape = Array.isArray(parsed?.[0]?.[2]) && JSON.parse(parsed[0][2])?.[0]?.length >= 100;

Try / catch

try { return await googleTts.synthesize(text); } catch (e) { if (e.message === 'Google TTS returned empty audio') return fallbackProvider(text); throw e; }

Prevention

When it happens

Trigger: The RPC returns an in-body error envelope (e.g. unknown text encoding, unsupported language, empty text) rather than audio; the batchexecute response layout changed so index [3]/[0][2] now points at the wrong chunk.

Common situations: Empty or whitespace-only text passed to synthesize; very long text exceeding the RPC limit; Google changing the batchexecute response line format (breaking the fixed index parse).

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/a20cfb844e109751. Report an issue: GitHub.