chatboxai/chatbox · error · Error
Failed to search knowledge base (id: ${kbId}). Please try ag
Error message
Failed to search knowledge base (id: ${kbId}). Please try again later. What it means
Thrown by Gemini.listModels() (built-in Google Gemini provider) when GET `${geminiAPIHost}/v1beta/models?key=...` returns a body without a top-level `models` array. Unlike the custom variant, this method is NOT wrapped in a swallowing try/catch, so the ApiError propagates to the caller. Google's ListModels response is `{ models: [...] }`; anything else is an error envelope (auth/quota) or a misrouted response.
Source
Thrown at src/main/knowledge-base/file-loaders.ts:473
}
return results.map((r) => ({
id: r.id,
score: r.score,
...r.metadata,
}))
}
} catch (e) {
log.error(`[FILE] Failed to search: kbId=${kbId}, queryLength=${query.length}`, e)
sentry.withScope((scope) => {
scope.setTag('component', 'knowledge-base-file')
scope.setTag('operation', 'search_knowledge_base')
scope.setExtra('kbId', kbId)
scope.setExtra('queryLength', query.length)
sentry.captureException(e)
})
throw new Error(`Failed to search knowledge base (id: ${kbId}). Please try again later.`)
}
}
// Read chunks from vector store
export async function readChunks(kbId: number, chunks: { fileId: number; chunkIndex: number }[]) {
try {
log.debug(`[FILE] Reading chunks: kbId=${kbId}, chunks=${chunks.length}`)
if (!chunks || chunks.length === 0) {
return []
}
const indexName = `kb_${kbId}`
const results: any[] = []
// Use single SQL query to get all chunks at once
log.debug(`[FILE] Using single SQL query via vectorStore.turso for ${chunks.length} chunks`)
View on GitHub (pinned to 81571269ad)
Solutions
- Inspect the JSON.stringify'd payload — Google's `{ error: { code, message, status } }` tells you auth (`UNAUTHENTICATED`), quota (`RESOURCE_EXHAUSTED`), or permission denied.
- Set `geminiAPIHost` to the base origin (e.g. `https://generativelanguage.googleapis.com`) — do not include `/v1beta`.
- Enable the 'Generative Language API' in the Google Cloud project that owns the key and remove referrer/IP restrictions for desktop usage.
- Wrap the listModels call in try/catch and fall back to a hardcoded model list so a transient listing failure does not block chat.
Example fix
// before
const models = await gemini.listModels() // propagates ApiError
// after
try {
const models = await gemini.listModels()
} catch (e) {
console.warn('Gemini listModels failed, using fallback', e)
return [{ modelId: 'gemini-2.5-flash', type: 'chat' }]
} Defensive patterns
Strategy: try-catch
Validate before calling
async function probeGeminiModels(host: string, key: string): Promise<boolean> {
const res = await fetch(`${host}/v1beta/models?key=${encodeURIComponent(key)}`)
const json = await res.json().catch(() => ({}))
return Array.isArray((json as any)?.models)
} Type guard
function isGeminiModelsResponse(json: unknown): json is { models: { name: string; supportedGenerationMethods: string[]; inputTokenLimit: number; outputTokenLimit: number; displayName: string }[] } {
return typeof json === 'object' && json !== null && Array.isArray((json as any).models)
} Try / catch
try { return await gemini.listModels() }
catch (e) {
if (e instanceof ApiError) { console.warn('Gemini listModels body:', e.message); return [] }
throw e
} Prevention
- Enable the Generative Language API on the Google project that owns the key.
- Use base-origin geminiAPIHost (no /v1beta suffix).
- Keep a fallback Gemini model list so listing failure does not block chat.
- Avoid API-key IP/referrer restrictions for desktop/mobile use.
When it happens
Trigger: Invalid or missing `geminiAPIKey` (Google returns `{ error: { code, message, status } }`); `geminiAPIHost` set to a value that already contains `/v1beta` (URL becomes `.../v1beta/v1beta/models`); the key is restricted to an API that does not include the Generative Language API; a proxy strips the `?key=` query string; region blocks the endpoint and a CDN returns an HTML/JSON error that parses without `models`.
Common situations: API key generated under a Google project where the Generative Language API is disabled; key with HTTP-referrer or IP restriction; user set a custom `geminiAPIHost` that includes a version path; corporate proxy returning a JSON error block; free-tier quota exceeded so the API returns an error object instead of the model list.
Related errors
- knowledge_base_parsed_content_too_large
- No content extracted from file
- local_parser_file_too_large
- pdf_password_protected
- Missing token for rerank provider: ${providerId}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/f44035bd152df418.
Report an issue: GitHub.