{"record":{"id":"dbaa4eee1225af16","repo":"moeru-ai/airi","slug":"failed-to-resolve-chat-provider-providerid","errorCode":null,"errorMessage":"Failed to resolve chat provider \"${providerId}\"","messagePattern":"Failed to resolve chat provider \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/stores/chat.ts","lineNumber":354,"sourceCode":"  }\n\n  function appendSendError(sessionId: string, error: unknown) {\n    chatSession.appendSessionMessage(sessionId, {\n      role: 'error',\n      content: errorMessageFrom(error) ?? 'Unknown chat operation failure',\n    })\n  }\n\n  async function executeSend(payload: ChatSendPayload): Promise<ChatSendResult> {\n    const providerId = activeProvider.value\n    const modelId = activeModel.value\n    if (!providerId || !modelId)\n      throw new Error('No active chat provider or model configured')\n\n    const messageCount = chatSession.getSessionMessages(payload.sessionId).length\n    const chatProvider = await providerStore.getProviderInstance<ChatProvider>(providerId)\n    if (!chatProvider)\n      throw new Error(`Failed to resolve chat provider \"${providerId}\"`)\n\n    await runtime.ingest(payload.text, {\n      model: modelId,\n      chatProvider,\n      attachments: payload.attachments,\n      input: payload.input,\n      toolReferences: payload.tools,\n      // Resolve this function after the request reaches the per-session queue.\n      // The history then contains tool names from every earlier queued turn.\n      tools: async () => {\n        const references = collectToolReferences(payload.sessionId, payload.tools)\n        return llmToolsStore.getToolsByNames(...references.map(tool => tool.name))\n      },\n    }, payload.sessionId)\n\n    return {\n      messages: chatSession.getSessionMessages(payload.sessionId)\n        .slice(messageCount)","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/stage-ui/src/stores/chat.ts#L336-L372","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the provider config is fully valid and the instance is loaded before allowing send (validate on selection).","If a provider cannot instantiate, clear activeProvider and prompt reconfiguration instead of leaving a dangling id.","Confirm the provider definition is registered in the current build (see getDefinedProvider).","Catch this error in the send action and surface a 'provider not available, reconfigure' message."],"exampleFix":"// before\nconst chatProvider = await providerStore.getProviderInstance<ChatProvider>(providerId)\nif (!chatProvider)\n  throw new Error(`Failed to resolve chat provider \"${providerId}\"`)\n\n// after: surface actionable guidance\nconst chatProvider = await providerStore.getProviderInstance<ChatProvider>(providerId)\nif (!chatProvider) {\n  appendSendError(payload.sessionId, new Error(\n    `Chat provider \"${providerId}\" is not configured. Open settings to set it up.`,\n  ))\n  return { ok: false }\n}","handlingStrategy":"validation","validationCode":"import { getDefinedProvider } from '../../libs/providers/providers'\n\nasync function canResolveChatProvider(providerId: string | null | undefined): Promise<boolean> {\n  if (!providerId)\n    return false\n  if (!getDefinedProvider(providerId))\n    return false\n  const instance = await providerStore.getProviderInstance(providerId)\n  return !!instance\n}\n\nif (!(await canResolveChatProvider(activeProvider.value))) {\n  // prompt reconfiguration\n  return\n}","typeGuard":"function isChatProviderInstance(value: unknown): value is ChatProvider {\n  return typeof value === 'object' && value !== null\n    && typeof (value as ChatProvider).ingest === 'function'\n}","tryCatchPattern":"try {\n  return await executeSend(payload)\n}\ncatch (error) {\n  if (String(error).includes('Failed to resolve chat provider')) {\n    appendSendError(payload.sessionId, new Error(\n      `Chat provider \"${activeProvider.value}\" is not available. Open settings to reconfigure.`,\n    ))\n    return { ok: false }\n  }\n  throw error\n}","preventionTips":["Validate the active provider's config is complete and its definition is registered before enabling send.","When a provider cannot instantiate, clear activeProvider and prompt reconfiguration instead of leaving a dangling id.","Confirm the provider definition is imported/registered in the current build."],"tags":["validation","state","chat","providers","config"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}