{"record":{"id":"39dab6d218bd62fb","repo":"chatboxai/chatbox","slug":"embedding-model-is-required","errorCode":null,"errorMessage":"Embedding model is required","messagePattern":"Embedding model is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/knowledge-base/ipc-handlers.ts","lineNumber":106,"sourceCode":"        name: string\n        embeddingModel: string\n        rerankModel: string\n        visionModel?: string\n        documentParser?: { type: string; mineru?: { apiToken: string } }\n        providerMode?: 'chatbox-ai' | 'custom'\n      }\n    ) => {\n      try {\n        log.info(\n          `ipcMain: kb:create, name=${name}, embeddingModel=${embeddingModel}, rerankModel=${rerankModel}, visionModel=${visionModel}, documentParser=${documentParser?.type || 'default'}, providerMode=${providerMode || 'not specified'}`\n        )\n\n        // Validate required fields\n        if (!name || !name.trim()) {\n          throw new Error('Knowledge base name is required')\n        }\n        if (!embeddingModel || !embeddingModel.trim()) {\n          throw new Error('Embedding model is required')\n        }\n\n        const db = getDatabase()\n        const documentParserJson = documentParser ? JSON.stringify(documentParser) : null\n        const rs = await db.execute({\n          sql: 'INSERT INTO knowledge_base (name, embedding_model, rerank_model, vision_model, document_parser, provider_mode) VALUES (?, ?, ?, ?, ?, ?)',\n          args: [\n            name.trim(),\n            embeddingModel,\n            rerankModel || null,\n            visionModel || null,\n            documentParserJson,\n            providerMode || null,\n          ],\n        })\n        const id = rs.lastInsertRowid\n\n        if (!id) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/main/knowledge-base/ipc-handlers.ts#L88-L124","documentation":"Thrown by getProviderSettings() when `setting.provider` is non-empty but no matching provider base info is found in the combined list of system (builtin registry) providers plus user `customProviders`. This means the provider id refers to something that is neither registered as a builtin nor defined as a custom provider in global settings — an orphaned reference.","triggerScenarios":"A saved session references a provider id that was removed in an app update (builtin deleted); a custom provider was deleted from globalSettings.customProviders but a session still references it; the provider id is misspelled or has trailing whitespace; settings imported from another installation that had different custom providers; provider id case mismatch (registry is case-sensitive).","commonSituations":"Downgrade or upgrade removed/renamed a builtin provider; user syncs sessions across devices without syncing customProviders; manually edited settings.json introduced a typo; a custom provider export/import lost the provider definitions; migration renamed a provider id without a back-compat alias.","solutions":["Check `getBuiltinProviderIds()` and `globalSettings.customProviders` for the exact id in `setting.provider` — a mismatch (whitespace, case, stale id) is the usual cause.","If the provider was deleted, re-add it (recreate the custom provider or re-enable the builtin) or switch the session to a current provider.","Add a settings-repair step on load that maps retired provider ids to their successors and resets orphaned sessions to the default provider.","If importing sessions, also import the matching customProviders so the reference resolves."],"exampleFix":"// before\nconst { providerSetting } = getProviderSettings(session, globals)\n// throws 'Cannot find model with provider: old-provider'\n\n// after: repair orphaned references before resolving\nconst known = new Set([...getBuiltinProviderIds(), ...(globals.customProviders||[]).map(p=>p.id)])\nif (!known.has(session.provider)) session.provider = getBuiltinProviderIds()[0]\nconst { providerSetting } = getProviderSettings(session, globals)","handlingStrategy":"validation","validationCode":"function knownProviderIds(globals: Settings): Set<string> {\n  return new Set([...getBuiltinProviderIds(), ...(globals.customProviders || []).map(p => p.id)])\n}\nif (session.provider && !knownProviderIds(globals).has(session.provider)) session.provider = getBuiltinProviderIds()[0]","typeGuard":"function isKnownProvider(provider: string, globals: Settings): boolean {\n  return getBuiltinProviderIds().includes(provider) || (globals.customProviders || []).some(p => p.id === provider)\n}","tryCatchPattern":"try { return getProviderSettings(session, globals) }\ncatch (e) {\n  if (e instanceof Error && e.message.startsWith('Cannot find model with provider')) {\n    session.provider = getBuiltinProviderIds()[0]\n    return getProviderSettings(session, globals)\n  }\n  throw e\n}","preventionTips":["On settings load, validate every session's provider against known ids and remap orphans.","When deleting a custom provider, also rewrite sessions that referenced it.","Sync customProviders alongside sessions across devices."],"tags":["configuration","session-settings","provider","registry","migration"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}