moeru-ai/airi · error · Error

Failed to initialize speech provider

Error message

Failed to initialize speech provider

What it means

Thrown by the Deepgram TTS settings playground when `providersStore.getProviderInstance(providerId)` resolves to a falsy value. The store (packages/stage-ui/src/stores/providers/provider.ts:744) looks up the provider definition and calls its `createProvider(config)` factory, typed as returning a non-nullable ProviderInstance (packages/stage-ui/src/libs/providers/types.ts:199). This guard is therefore a runtime backstop: the Deepgram factory (built through the unspeech bridge) returned `undefined` instead of throwing, almost always because the saved config is incomplete (blank/whitespace API key).

Source

Thrown at packages/stage-pages/src/pages/settings/providers/speech/deepgram-tts.vue:33

const defaultModel = 'aura-2-thalia-en'

const defaultVoiceSettings = {}

const speechStore = useSpeechStore()
const providersStore = useProviderStore()
const providerStore = useProviderConfigStore()
const { configs: providers } = storeToRefs(providerStore)

const apiKeyConfigured = computed(() => !!providers.value[providerId]?.apiKey)

const availableVoices = computed(() => {
  return speechStore.availableVoices[providerId] || []
})

async function handleGenerateSpeech(input: string, voiceId: string, _useSSML: boolean) {
  const provider = await providersStore.getProviderInstance(providerId) as SpeechProviderWithExtraOptions<string>
  if (!provider) {
    throw new Error('Failed to initialize speech provider')
  }

  const providerConfig = providerStore.getProviderConfig(providerId)

  const model = providerConfig.model as string | undefined || defaultModel

  return await speechStore.speech(
    provider,
    model,
    input,
    voiceId,
    {
      ...providerConfig,
      ...defaultVoiceSettings,
    },
  )
}

View on GitHub (pinned to 677329427f)

Solutions

  1. Open Settings → Providers → Deepgram TTS and save a non-empty API key, then let the built-in validation pass.
  2. Re-run the playground (or restart the app) so `getProviderInstance` rebuilds the instance from the fresh config instead of any cached falsy result.
  3. Check the browser console for `Error creating provider instance for ...` — the underlying factory reason is logged just before this throw.
  4. Verify the config actually persisted (provider config store) — an unsaved key leaves an empty object that passes the store's presence check but produces no instance.
  5. If config is provably valid and it still fails, report it: a factory returning undefined violates the non-nullable `createProvider` contract.

Example fix

// before
const provider = await providersStore.getProviderInstance(providerId) as SpeechProviderWithExtraOptions<string>
if (!provider)
  throw new Error('Failed to initialize speech provider')

// after
const config = providerStore.getProviderConfig(providerId)
if (!config?.apiKey?.trim())
  throw new Error('Deepgram API key is empty. Save credentials in provider settings first.')
const provider = await providersStore.getProviderInstance(providerId) as SpeechProviderWithExtraOptions<string>
if (!provider || typeof provider.speech !== 'function')
  throw new Error('Deepgram factory returned no usable instance — check saved config and console logs')
Defensive patterns

Strategy: validation

Validate before calling

const apiKeyConfigured = computed(() => !!providers.value[providerId]?.apiKey?.trim())
// template: <SpeechPlayground :disabled="!apiKeyConfigured" ... />
if (!apiKeyConfigured.value)
  throw new Error('Save a Deepgram API key before generating speech')

Type guard

function isSpeechProvider(v: unknown): v is SpeechProvider<string> {
  return typeof v === 'object' && v !== null && typeof (v as SpeechProvider<string>).speech === 'function'
}

Try / catch

try {
  const provider = await providersStore.getProviderInstance(providerId)
  ...
}
catch (error) {
  // Distinguish store failures (credentials/definition missing) from factory declines
  errorMessage.value = error instanceof Error ? error.message : String(error)
}

Prevention

When it happens

Trigger: Clicking Generate in Settings → Providers → Deepgram TTS playground before a valid API key is saved; an API key stored as an empty or whitespace-only string (the store only throws 'Provider credentials ... not found' when the whole config object is absent, not when fields are blank); generating right after editing credentials while a stale falsy build result lingers in the per-session `providerInstanceCache`.

Common situations: User adds the provider but skips onboarding; user pasted a key with trailing spaces or cleared the field and saved; switching between API keys without restarting the app; environments where the unspeech bridge factory declines on empty strings rather than raising.

Related errors


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/a350a869c24c2692. Report an issue: GitHub.