{"record":{"id":"197ec4a7eb2ec886","repo":"moeru-ai/airi","slug":"failed-to-initialize-speech-provider-197ec4","errorCode":null,"errorMessage":"Failed to initialize speech provider","messagePattern":"Failed to initialize speech provider","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/stage-pages/src/pages/settings/providers/speech/openai-audio-speech.vue","lineNumber":84,"sourceCode":"    return voice.compatibleModels.includes(selectedModel)\n  })\n})\n\n// Load models and voices on mount\nonMounted(async () => {\n  await providersStore.loadModelsForConfiguredProviders()\n  await providersStore.fetchModelsForProvider(providerId)\n  // Load voices\n  // NOTE: OpenAI does not provide an API endpoint to retrieve available voices.\n  // Voices are hardcoded in provider metadata - this is a provider limitation, not an application limitation.\n  await speechStore.loadVoicesForProvider(providerId)\n})\n\n// Generate speech with OpenAI-specific parameters\nasync function handleGenerateSpeech(input: string, voiceId: string, _useSSML: boolean) {\n  const provider = await providersStore.getProviderInstance<SpeechProvider<string>>(providerId)\n  if (!provider) {\n    throw new Error('Failed to initialize speech provider')\n  }\n\n  // Get provider configuration\n  const providerConfig = providerStore.getProviderConfig(providerId)\n\n  // Use the reactive model computed property (not a local variable)\n  const modelToUse = model.value || defaultModel\n\n  return await speechStore.speech(\n    provider,\n    modelToUse,\n    input,\n    voiceId,\n    {\n      ...providerConfig,\n      ...defaultVoiceSettings,\n    },\n  )","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-pages/src/pages/settings/providers/speech/openai-audio-speech.vue#L66-L102","documentation":"Thrown by the OpenAI audio speech playground when `getProviderInstance<SpeechProvider<string>>(providerId)` resolves falsy. Voices for OpenAI are hardcoded in provider metadata (no list-endpoint), but the instance still requires the OpenAI API key from persisted config. `getProviderInstance` throws its own distinct errors for a missing definition or entirely missing config, so this guard catches the remaining case: the factory built nothing (undefined) from an incomplete/blank config despite the non-nullable `Promise<R>` type.","triggerScenarios":"Clicking Generate before saving an OpenAI API key; key stored as empty/whitespace so the config object exists (store does not throw) but the factory declines; generating before the onMounted voice/model loads complete while credentials were never entered.","commonSituations":"Fresh installs where onboarding was skipped; key cleared and saved after testing other providers; org keys rotated in the OpenAI dashboard without updating AIRI; confusion between the chat provider key and the audio-speech provider entry (separate config slots).","solutions":["Save a valid OpenAI API key under the audio speech provider entry in Settings → Providers and pass validation.","Reload the playground after saving so the instance is rebuilt from fresh config.","Check the console for `Error creating provider instance for ...` — the factory's underlying reason is logged there.","Confirm you configured the OpenAI audio provider specifically, not only the chat provider.","If the key is valid and it still fails, report the silent-undefined factory behavior."],"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('OpenAI 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('OpenAI audio 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 an OpenAI 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":["Configure the OpenAI audio-speech provider entry specifically, not just chat.","Reload the playground after key changes.","Remember voices are hardcoded (no voices endpoint) — init failures are config, not catalogue, problems."],"tags":["speech","provider","initialization","api-key","openai"],"backgroundTag":"provider-instance-undefined","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}