{"record":{"id":"dc3a1a1fc225221f","repo":"moeru-ai/airi","slug":"failed-to-initialize-speech-provider-dc3a1a","errorCode":null,"errorMessage":"Failed to initialize speech provider","messagePattern":"Failed to initialize speech provider","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-pages/src/pages/settings/providers/speech/google-gemini-audio-speech.vue","lineNumber":84,"sourceCode":"})\n\nconst apiKeyConfigured = computed(() => !!providers.value[providerId]?.apiKey)\n\nonMounted(async () => {\n  ensureProviderConfig()\n\n  if (!config.value?.model)\n    model.value = defaultModel\n\n  await providersStore.loadModelsForConfiguredProviders()\n  await providersStore.fetchModelsForProvider(providerId)\n  await speechStore.loadVoicesForProvider(providerId)\n})\n\nasync function handleGenerateSpeech(input: string, voiceId: string, _useSSML: boolean, modelId?: string) {\n  const provider = await providersStore.getProviderInstance<SpeechProvider<string>>(providerId)\n  if (!provider)\n    throw new Error('Failed to initialize speech provider')\n\n  const providerConfig = providerStore.getProviderConfig(providerId)\n  const modelToUse = modelId || model.value || defaultModel\n  const voiceToUse = voiceId || '' as string\n\n  return await speechStore.speech(\n    provider,\n    modelToUse,\n    input,\n    voiceToUse,\n    providerConfig,\n  )\n}\n\nconst {\n  isValidating,\n  isValid,\n  validationMessage,","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-pages/src/pages/settings/providers/speech/google-gemini-audio-speech.vue#L66-L102","documentation":"Thrown by the Gemini audio speech playground when `getProviderInstance<SpeechProvider<string>>(providerId)` resolves falsy before synthesis. The store resolves the Google Gemini speech definition and calls its `createProvider(config)`; the declared return type is non-nullable, so hitting this branch means the factory declined to build with the persisted config (typically a missing/blank Google API key) rather than the store's own failure paths, which throw different errors (`Provider definition ... not found`, `Provider credentials ... not found`).","triggerScenarios":"Pressing Generate in the Gemini speech playground while `providers.value[providerId].apiKey` is blank; running before the onMounted model/voice fetches complete while credentials were never saved; config present as an object (so the store does not throw) but with unusable field values.","commonSituations":"New provider added without completing the API key step; key removed after a session that already used another provider; workspace where the key lives in a different provider entry (gemini chat vs gemini audio speech ids); silent factory decline on whitespace-only keys.","solutions":["Save a non-empty Google API key for this provider entry in Settings → Providers and wait for validation to pass.","Re-enter the playground after saving so the instance is rebuilt from current config.","Check console for the store's `Error creating provider instance for ...` log line for the underlying cause.","Confirm you configured the audio-speech provider entry itself, not the chat/generative one — they are separate ids.","If valid credentials still yield falsy, file an issue: the factory violates the non-nullable createProvider contract."],"exampleFix":"// before\nconst provider = await providersStore.getProviderInstance<SpeechProvider<string>>(providerId)\nif (!provider)\n  throw new Error('Failed to initialize speech provider')\n\n// after\nconst config = providerStore.getProviderConfig(providerId)\nif (!config?.apiKey?.trim())\n  throw new Error('Gemini API key is empty. Save it in provider settings first.')\nconst provider = await providersStore.getProviderInstance<SpeechProvider<string>>(providerId)\nif (!provider || typeof provider.speech !== 'function')\n  throw new Error('Gemini speech factory returned no usable instance — check config and console logs')","handlingStrategy":"validation","validationCode":"const apiKeyConfigured = computed(() => !!providers.value[providerId]?.apiKey?.trim())\nif (!apiKeyConfigured.value)\n  throw new Error('Save a Google API key before generating speech')","typeGuard":"function isSpeechProvider(v: unknown): v is SpeechProvider<string> {\n  return typeof v === 'object' && v !== null && typeof (v as SpeechProvider<string>).speech === 'function'\n}","tryCatchPattern":"try { const provider = await providersStore.getProviderInstance<SpeechProvider<string>>(providerId) }\ncatch (error) { showError(errorMessageFrom(error)) }","preventionTips":["Complete provider onboarding (key + validation) before entering the playground.","Disable generate until the onMounted model/voice loads finish.","Confirm you configured the audio-speech provider entry, not the chat one."],"tags":["speech","provider","initialization","api-key","gemini"],"backgroundTag":"provider-instance-undefined","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}