decolua/9router · error · Error

OpenAI TTS failed: ${res.status}

Error message

OpenAI TTS failed: ${res.status}

What it means

Thrown when the OpenAI /v1/audio/speech endpoint returns a non-2xx HTTP status. The code first tries to surface OpenAI's structured error message (err.error.message) and falls back to this template containing the HTTP status code. It wraps any upstream rejection: invalid key, bad model, billing, rate limits.

Source

Thrown at open-sse/handlers/ttsProviders/openai.js:28

    let ttsModel = DEFAULT_TTS_MODEL;
    let voice = "alloy";
    if (model && model.includes("/")) {
      const parts = model.split("/");
      if (parts.length === 2) [ttsModel, voice] = parts;
    } else if (model) {
      voice = model;
    }

    const baseUrl = (credentials.baseUrl || "https://api.openai.com").replace(/\/+$/, "");
    const res = await fetch(`${baseUrl}/v1/audio/speech`, {
      method: "POST",
      headers: { "Content-Type": "application/json", "Authorization": `Bearer ${credentials.apiKey}` },
      body: JSON.stringify({ model: ttsModel, voice, input: text }),
    });
    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      throw new Error(err?.error?.message || `OpenAI TTS failed: ${res.status}`);
    }
    const buf = await res.arrayBuffer();
    return { base64: Buffer.from(buf).toString("base64"), format: "mp3" };
  },
};

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Check the HTTP status in the message: 401 -> fix API key, 429 -> rate limit/billing, 404 -> model name
  2. Verify the OpenAI account has billing credit and the key is active
  3. Confirm the TTS model name (default from PROVIDER_MEDIA openai.ttsConfig.defaultModel) is valid, e.g. gpt-4o-mini-tts or tts-1
  4. Check network/proxy interference if status is 5xx or 403
  5. Retry with backoff on 429/5xx
Defensive patterns

Strategy: retry

Validate before calling

if (!credentials?.apiKey) throw new Error("OpenAI TTS: missing API key");
if (!/^(gpt-4o-mini-tts|tts-1|tts-1-hd)$/.test(ttsModel)) throw new Error(`Unknown OpenAI TTS model: ${ttsModel}`);

Type guard

function isOpenAiHttpError(e) {
  return e instanceof Error && /^OpenAI TTS failed: \d{3}$/.test(e.message);
}

Try / catch

try {
  return await openaiTts.synthesize(text, model, creds);
} catch (e) {
  const m = e.message.match(/OpenAI TTS failed: (\d{3})/);
  if (m && (m[1] === "429" || m[1].startsWith("5"))) return retryWithBackoff(() => openaiTts.synthesize(text, model, creds));
  throw e;
}

Prevention

When it happens

Trigger: POST to OpenAI audio/speech fails: 401 invalid API key, 404 wrong model name (e.g. tts-1 typo), 429 rate limit, 402/429 billing/quota exceeded, or a proxy returning an error page without JSON parseable error.message.

Common situations: Expired or revoked OpenAI keys, insufficient credits, requesting a model the account lacks access to, or corporate proxies/VPNs returning non-JSON error bodies so the fallback status-code message appears.

Related errors


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