{"record":{"id":"ba3586ccbb3aaf97","repo":"moeru-ai/airi","slug":"no-active-chat-provider-or-model-configured","errorCode":null,"errorMessage":"No active chat provider or model configured","messagePattern":"No active chat provider or model configured","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/stores/chat.ts","lineNumber":349,"sourceCode":"\n    for (const tool of selectedTools)\n      names.add(tool.name)\n\n    return [...names].map(name => ({ name }))\n  }\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      },","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/stage-ui/src/stores/chat.ts#L331-L367","documentation":"Thrown synchronously at the start of chat store executeSend when activeProvider or activeModel is falsy. The send pipeline requires both a provider id and a model id to resolve a ChatProvider instance and call runtime.ingest; without them it cannot proceed. This is a UI-state precondition error, not a network error.","triggerScenarios":"The user triggers a send (chat input submit) before selecting a provider/model, or the persisted active provider/model was cleared/expired. Also when a provider config is invalid so activeProvider becomes empty after validation, but the send button is still enabled.","commonSituations":"First-run with no provider configured; provider config deleted making activeProvider stale; model list not yet loaded so activeModel is empty; UI bug allowing send while selection is incomplete.","solutions":["Disable the send control until both activeProvider and activeModel are set.","On startup, ensure a default provider/model is selected or prompt the user to configure one.","When a provider is removed, clear activeProvider only if it matches and re-select a valid one.","Catch this error in the send action and show a 'configure a provider' prompt instead of a raw error."],"exampleFix":"// before\nconst providerId = activeProvider.value\nconst modelId = activeModel.value\nif (!providerId || !modelId)\n  throw new Error('No active chat provider or model configured')\n\n// after: guard at the UI layer so executeSend is never called unprepared\n// (in the component)\nconst canSend = computed(() => !!activeProvider.value && !!activeModel.value && payload.value.trim())\n<button :disabled=\"!canSend\" @click=\"send\">Send</button>","handlingStrategy":"validation","validationCode":"import { computed } from 'vue'\n\nconst canSend = computed(() => !!activeProvider.value && !!activeModel.value)\n\n// in the send action\nfunction send(payload: ChatSendPayload) {\n  if (!canSend.value) {\n    // prompt user to select/configure a provider and model\n    return\n  }\n  return executeSend(payload)\n}","typeGuard":"function hasActiveChatSelection(provider: unknown, model: unknown): provider is string {\n  return typeof provider === 'string' && provider.length > 0\n    && typeof model === 'string' && model.length > 0\n}","tryCatchPattern":"try {\n  return await executeSend(payload)\n}\ncatch (error) {\n  if (String(error).includes('No active chat provider or model')) {\n    // open settings / prompt configuration; do not retry until resolved\n  }\n  throw error\n}","preventionTips":["Disable the send control until both activeProvider and activeModel are set.","On startup, select a default provider/model or prompt the user to configure one.","When a provider is removed, clear activeProvider only if it matches and re-select a valid default."],"tags":["validation","state","chat","providers","config","ui"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}