{"record":{"id":"0f509e5ecbca48d8","repo":"chatboxai/chatbox","slug":"knowledge-base-kbid-not-found","errorCode":null,"errorMessage":"Knowledge base ${kbId} not found","messagePattern":"Knowledge base (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/knowledge-base/ipc-handlers.ts","lineNumber":222,"sourceCode":"    }\n  )\n\n  ipcMain.handle('kb:delete', async (_event, kbId: number): Promise<{ success: boolean; error?: string }> => {\n    try {\n      log.info(`ipcMain: kb:delete, kbId=${kbId}`)\n\n      if (!kbId || kbId <= 0) {\n        throw new Error('Invalid knowledge base ID')\n      }\n\n      await withTransaction(async () => {\n        const db = getDatabase()\n        const vectorStore = getVectorStore()\n\n        // Verify knowledge base exists before deletion\n        const kbExists = await db.execute('SELECT id FROM knowledge_base WHERE id = ?', [kbId])\n        if (!kbExists.rows[0]) {\n          throw new Error(`Knowledge base ${kbId} not found`)\n        }\n\n        // 1. Delete associated files from kb_file\n        await db.execute({\n          sql: 'DELETE FROM kb_file WHERE kb_id = ?',\n          args: [kbId],\n        })\n        log.info(`[IPC] Deleted file records for kbId=${kbId}`)\n\n        // 2. Delete the knowledge base entry\n        await db.execute({\n          sql: 'DELETE FROM knowledge_base WHERE id = ?',\n          args: [kbId],\n        })\n        log.info(`[IPC] Deleted knowledge base record for kbId=${kbId}`)\n\n        // 3. Delete vector index\n        await vectorStore.deleteIndex({ indexName: `kb_${kbId}` })","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/main/knowledge-base/ipc-handlers.ts#L204-L240","documentation":"Thrown by authenticatedAfetch() before any network call when `getTokens()` resolves to null — i.e. the user is not logged in / has no stored access+refresh token pair. This is the entry guard for Chatbox AI authenticated endpoints: every authenticated request requires a valid token pair, so a null token short-circuits immediately.","triggerScenarios":"User opened a feature requiring Chatbox AI authentication without completing login; tokens were cleared by a prior refresh failure (clearTokens runs on refresh error); fresh install / new device profile with no stored session; logout just completed but a background task still tried an authenticated call; token storage (e.g. keychain) returned null due to a permission/IO error.","commonSituations":"Background sync, license check, or chat retry runs after the user signed out; mobile app reinstall lost the keychain entry; OS keychain access denied so getTokens() yields null even though the user 'is logged in' from the UI's perspective; race between logout and an in-flight queued request.","solutions":["Before calling authenticated endpoints, check the login state and prompt the user to sign in if no tokens are present.","Coordinate logout so in-flight/queued authenticated requests are cancelled rather than allowed to hit this guard.","Verify token storage permissions (keychain access on mobile, IndexedDB/localStorage on web) so getTokens() does not silently return null.","On app start, if a feature expects auth, run a login-status check and route to the login screen when tokens are absent."],"exampleFix":"// before\nconst res = await authedAfetch(url, init)  // throws 'No authentication tokens available'\n\n// after\nconst tokens = await getTokens()\nif (!tokens) { routeToLogin(); return }\nconst res = await authedAfetch(url, init)","handlingStrategy":"validation","validationCode":"const tokens = await getTokens()\nif (!tokens) { routeToLogin(); throw new Error('Login required') }","typeGuard":"function hasTokens(t: { accessToken?: string; refreshToken?: string } | null): t is { accessToken: string; refreshToken: string } {\n  return !!t && typeof t.accessToken === 'string' && typeof t.refreshToken === 'string'\n}","tryCatchPattern":"try { return await authedAfetch(url, init) }\ncatch (e) {\n  if (e instanceof ApiError && e.message.includes('No authentication tokens available')) routeToLogin()\n  throw e\n}","preventionTips":["Check login state before calling authenticated endpoints.","Cancel queued authenticated requests on logout.","Verify token-storage permissions so getTokens() does not silently return null."],"tags":["auth","tokens","chatbox-ai","precondition","login"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}