{"record":{"id":"016fef101e62bdd3","repo":"moeru-ai/airi","slug":"failed-to-initialize-speech-provider-016fef","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/comet-api-speech.vue","lineNumber":103,"sourceCode":"\n// Ensure provider config is initialized on mount\nonMounted(() => {\n  if (!providers.value[providerId]) {\n    providers.value[providerId] = {}\n  }\n  if (!providers.value[providerId].model) {\n    providers.value[providerId].model = defaultModel\n  }\n  if (!providers.value[providerId].voice) {\n    providers.value[providerId].voice = 'alloy'\n  }\n})\n\n// Generate speech with OpenAI-compatible parameters\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\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 = modelId || model.value || defaultModel\n\n  return await speechStore.speech(\n    provider,\n    modelToUse,\n    input,\n    voiceId || (voice.value as string),\n    {\n      ...providerConfig,\n      ...defaultVoiceSettings,\n      speed: speed.value,\n    },","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-pages/src/pages/settings/providers/speech/comet-api-speech.vue#L85-L121","documentation":"The CometAPI speech preview awaits getProviderInstance(providerId) cast to SpeechProvider<string> and throws this generic message on a falsy instance. Usually the missing-credentials throw from provider.ts fires first when no API key is saved (onMounted only defaults model and voice); this guard covers a factory returning nothing.","triggerScenarios":"Clicking generate before configuring the CometAPI credentials; onMounted defaults (defaultModel, voice 'alloy') applied while the API key is still absent.","commonSituations":"Fresh install with the speech provider selected but unconfigured; tests exercising the page without seeded credentials.","solutions":["Save the CometAPI credentials in Settings > Providers > Speech and retry.","Verify providerId matches the registered OpenAI-compatible speech definition.","Gate the generate button on credential presence.","Surface the underlying provider error instead of the generic message for diagnosis."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!providers.value[providerId]?.apiKey) {\n  // provider unconfigured — disable generate and link to settings\n}","typeGuard":null,"tryCatchPattern":"catch (e) {\n  const msg = errorMessageFrom(e) ?? ''\n  if (msg.includes('credentials') || msg.includes('initialize speech provider'))\n    openProviderSettings(providerId)\n  else\n    throw e\n}","preventionTips":["Disable generate until the provider's credentials exist.","Apply onMounted defaults only when credentials are present so UI state matches constructability.","Reuse the same credential gate across every OpenAI-compatible speech provider page."],"tags":["speech","tts","provider","configuration","openai-compatible"],"backgroundTag":"provider-initialization-failed","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}