{"record":{"id":"bc563e62f778ab68","repo":"chatboxai/chatbox","slug":"failed-to-create-knowledge-base","errorCode":null,"errorMessage":"Failed to create knowledge base","messagePattern":"Failed to create knowledge base","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/knowledge-base/ipc-handlers.ts","lineNumber":125,"sourceCode":"        }\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) {\n          throw new Error('Failed to create knowledge base')\n        }\n\n        log.info(`[IPC] Knowledge base created successfully: id=${id}, name=${name}`)\n        return { id, name: name.trim() }\n      } catch (error: unknown) {\n        log.error(`ipcMain: kb:create failed for name=${name}`, error)\n        sentry.withScope((scope) => {\n          scope.setTag('component', 'knowledge-base-ipc')\n          scope.setTag('operation', 'kb_create')\n          scope.setExtra('name', name)\n          scope.setExtra('embeddingModel', embeddingModel)\n          scope.setExtra('rerankModel', rerankModel)\n          scope.setExtra('visionModel', visionModel)\n          scope.setExtra('documentParser', documentParser?.type)\n          sentry.captureException(error)\n        })\n        throw error\n      }","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/main/knowledge-base/ipc-handlers.ts#L107-L143","documentation":"Thrown by getModel() when `settings.provider` is falsy. Identical precondition to the one in getProviderSettings but at the top-level model factory — getModel() will not even attempt a registry lookup without a provider. The message is the same ('Model provider must not be empty.') so callers cannot tell which function threw from the message alone; the stack trace points to index.ts:156.","triggerScenarios":"getModel() invoked with a SessionSettings object whose `provider` is empty (e.g. before the user picks a model); a code path that builds a fresh settings object and forgets to copy `provider`; deserialised session after a migration that dropped the field; programmatic callers passing `{ modelId: '...' }` without `provider`.","commonSituations":"Background tasks (e.g. quick-action, agent loop, translation) call getModel() with a partial settings snapshot that lost `provider`; new chat created before defaults applied; settings loaded from a corrupt file; refactor changed the SessionSettings shape and a caller was not updated.","solutions":["Before calling getModel(), assert `settings.provider` is non-empty and fall back to the global default provider.","Centralise session construction so `provider` is always set from a single source of truth.","Add a runtime guard at the UI/controller boundary that prevents dispatching chat/paint actions until a provider is chosen.","Run a settings-migration/repair on load to backfill `provider` from `globalSettings.defaultModelProvider`."],"exampleFix":"// before\nconst model = getModel(session, globals, config, deps)  // throws if session.provider empty\n\n// after\nif (!session.provider) {\n  throw new Error('Cannot start chat: no provider selected')  // surfaced clearly to UI\n}\nconst model = getModel(session, globals, config, deps)","handlingStrategy":"validation","validationCode":"function ensureProvider(session: SessionSettings, globals: Settings): string {\n  if (!session.provider) session.provider = (globals as any).defaultModelProvider || getBuiltinProviderIds()[0]\n  return session.provider\n}","typeGuard":"function hasProvider(s: { provider?: string }): s is { provider: string } {\n  return typeof s.provider === 'string' && s.provider.length > 0\n}","tryCatchPattern":"if (!hasProvider(settings)) throw new UserFacingError('Cannot start: no provider selected')\nconst model = getModel(settings, globals, config, deps)","preventionTips":["Gate every getModel() call site on a non-empty provider.","Centralise session construction so provider is always set.","Add a load-time repair that backfills provider from the global default."],"tags":["configuration","session-settings","provider","precondition","factory"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}