moeru-ai/airi · error · Error

Failed to resolve chat provider "${providerId}"

Error message

Failed to resolve chat provider "${providerId}"

What it means

Thrown by chat store executeSend after providerStore.getProviderInstance<ChatProvider>(providerId) resolves to a falsy value. The send pipeline needs an instantiated ChatProvider to pass to runtime.ingest; if the provider store cannot build/resolve an instance for the active id, sending cannot proceed. This usually means the provider config is incomplete or failed to instantiate.

Source

Thrown at packages/stage-ui/src/stores/chat.ts:354

  }

  function appendSendError(sessionId: string, error: unknown) {
    chatSession.appendSessionMessage(sessionId, {
      role: 'error',
      content: errorMessageFrom(error) ?? 'Unknown chat operation failure',
    })
  }

  async function executeSend(payload: ChatSendPayload): Promise<ChatSendResult> {
    const providerId = activeProvider.value
    const modelId = activeModel.value
    if (!providerId || !modelId)
      throw new Error('No active chat provider or model configured')

    const messageCount = chatSession.getSessionMessages(payload.sessionId).length
    const chatProvider = await providerStore.getProviderInstance<ChatProvider>(providerId)
    if (!chatProvider)
      throw new Error(`Failed to resolve chat provider "${providerId}"`)

    await runtime.ingest(payload.text, {
      model: modelId,
      chatProvider,
      attachments: payload.attachments,
      input: payload.input,
      toolReferences: payload.tools,
      // Resolve this function after the request reaches the per-session queue.
      // The history then contains tool names from every earlier queued turn.
      tools: async () => {
        const references = collectToolReferences(payload.sessionId, payload.tools)
        return llmToolsStore.getToolsByNames(...references.map(tool => tool.name))
      },
    }, payload.sessionId)

    return {
      messages: chatSession.getSessionMessages(payload.sessionId)
        .slice(messageCount)

View on GitHub (pinned to 27111382b4)

Solutions

  1. Ensure the provider config is fully valid and the instance is loaded before allowing send (validate on selection).
  2. If a provider cannot instantiate, clear activeProvider and prompt reconfiguration instead of leaving a dangling id.
  3. Confirm the provider definition is registered in the current build (see getDefinedProvider).
  4. Catch this error in the send action and surface a 'provider not available, reconfigure' message.

Example fix

// before
const chatProvider = await providerStore.getProviderInstance<ChatProvider>(providerId)
if (!chatProvider)
  throw new Error(`Failed to resolve chat provider "${providerId}"`)

// after: surface actionable guidance
const chatProvider = await providerStore.getProviderInstance<ChatProvider>(providerId)
if (!chatProvider) {
  appendSendError(payload.sessionId, new Error(
    `Chat provider "${providerId}" is not configured. Open settings to set it up.`,
  ))
  return { ok: false }
}
Defensive patterns

Strategy: validation

Validate before calling

import { getDefinedProvider } from '../../libs/providers/providers'

async function canResolveChatProvider(providerId: string | null | undefined): Promise<boolean> {
  if (!providerId)
    return false
  if (!getDefinedProvider(providerId))
    return false
  const instance = await providerStore.getProviderInstance(providerId)
  return !!instance
}

if (!(await canResolveChatProvider(activeProvider.value))) {
  // prompt reconfiguration
  return
}

Type guard

function isChatProviderInstance(value: unknown): value is ChatProvider {
  return typeof value === 'object' && value !== null
    && typeof (value as ChatProvider).ingest === 'function'
}

Try / catch

try {
  return await executeSend(payload)
}
catch (error) {
  if (String(error).includes('Failed to resolve chat provider')) {
    appendSendError(payload.sessionId, new Error(
      `Chat provider "${activeProvider.value}" is not available. Open settings to reconfigure.`,
    ))
    return { ok: false }
  }
  throw error
}

Prevention

When it happens

Trigger: activeProvider is set to an id whose config is missing required fields (e.g. no apiKey), whose definition is not registered, or whose instance construction threw and was caught leaving the instance undefined. Also after a provider is deleted but activeProvider still references it.

Common situations: Provider config partially saved (missing apiKey/baseUrl); provider definition removed in a new build but id still persisted as active; provider instantiation failed silently; race where the provider store has not finished loading instances.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/dbaa4eee1225af16. Report an issue: GitHub.