decolua/9router · error · Error

No Gemini API key configured

Error message

No Gemini API key configured

What it means

The Gemini TTS provider's synthesize throws "No Gemini API key configured" when `credentials?.apiKey` is missing. Gemini TTS uses generateContent with AUDIO response modality and authenticates via the `key` query parameter, so without an API key the request cannot even be built correctly.

Source

Thrown at open-sse/handlers/ttsProviders/gemini.js:63

  header.writeUInt16LE(CHANNELS, 22);
  header.writeUInt32LE(SAMPLE_RATE, 24);
  header.writeUInt32LE(byteRate, 28);
  header.writeUInt16LE(blockAlign, 32);
  header.writeUInt16LE(BITS_PER_SAMPLE, 34);
  header.write("data", 36);
  header.writeUInt32LE(dataSize, 40);
  return Buffer.concat([header, pcmBuffer]);
}

// Build TTS prompt: add "Say [in {language}]:" prefix to force TTS mode
function buildPrompt(text, language) {
  if (/:\s/.test(text)) return text; // user already provided style instruction
  return language ? `Say in ${language}: ${text}` : `Say: ${text}`;
}

export default {
  async synthesize(text, model, credentials, _responseFormat, opts = {}) {
    if (!credentials?.apiKey) throw new Error("No Gemini API key configured");
    const { modelId, voiceId } = parseGeminiModelVoice(model);
    const url = `${TTS_BASE}/${modelId}:generateContent?key=${credentials.apiKey}`;
    const res = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        contents: [{ parts: [{ text: buildPrompt(text, opts.language) }] }],
        generationConfig: {
          responseModalities: ["AUDIO"],
          speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: voiceId } } },
        },
      }),
    });
    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      throw new Error(err?.error?.message || `Gemini TTS failed: ${res.status}`);
    }
    const data = await res.json();

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Create an API key in Google AI Studio and enter it as the Gemini provider's API key in the 9Router dashboard.
  2. Ensure the key is stored under `credentials.apiKey` — the exact field this guard checks.
  3. Verify the key works: `curl "https://generativelanguage.googleapis.com/v1beta/models?key=$KEY"` should list models.
  4. If you set GEMINI_API_KEY / GOOGLE_API_KEY in env, confirm it is actually passed into the provider credentials object rather than just exported.

Example fix

// before
await gemini.synthesize(text, "gemini-2.5-flash-preview-tts/Kore", {}); // no apiKey
// after
const creds = { apiKey: process.env.GEMINI_API_KEY };
if (!creds.apiKey) throw new Error("Set GEMINI_API_KEY for Gemini TTS");
await gemini.synthesize(text, "gemini-2.5-flash-preview-tts/Kore", creds);
Defensive patterns

Strategy: validation

Validate before calling

function requireGeminiCreds(creds) {
  if (typeof creds?.apiKey !== "string" || !creds.apiKey.trim()) {
    throw new Error("Gemini TTS needs an API key (Google AI Studio) configured as credentials.apiKey");
  }
  return { apiKey: creds.apiKey.trim() };
}

Type guard

function hasGeminiKey(creds) {
  return typeof creds === "object" && creds !== null && typeof creds.apiKey === "string" && creds.apiKey.trim() !== "";
}

Try / catch

try {
  const audio = await gemini.synthesize(text, model, creds);
} catch (e) {
  if (e.message === "No Gemini API key configured") {
    return res.status(400).json({ error: "Add a Gemini API key in the dashboard before using Gemini TTS" });
  }
  throw e;
}

Prevention

When it happens

Trigger: Routing a TTS request to the Gemini provider while no Gemini API key is configured: provider enabled in 9Router without credentials, key stored under a field other than `apiKey`, key removed later, or synthesize called directly with null credentials.

Common situations: Fresh setup where the Gemini API key was never entered in the dashboard; using an OAuth-based Gemini credential (which this provider does not read — it needs `apiKey`); key expired/deleted in Google AI Studio; env var set but not wired into the provider credentials object.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


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