chatboxai/chatbox · error · Error
Web search failed with status ${response.status}
Error message
Web search failed with status ${response.status} What it means
Thrown by searchNativeTavily (src/shared/services/native-web-search.ts:263) when POST ${apiHost||https://api.tavily.com}/search returns a non-2xx status. The body is { query, search_depth:'basic', include_domains:[], exclude_domains:[], max_results? } with Authorization: Bearer <apiKey>. The throw happens before body parsing, so only the raw HTTP status is reported. Unlike Querit, Tavily has no separate business error_code path, so any non-ok response is a hard failure.
Source
Thrown at src/shared/services/native-web-search.ts:263
search_depth: 'basic',
include_domains: [],
exclude_domains: [],
}
if (maxResults !== undefined) {
body.max_results = maxResults
}
const response = await fetchFn(`${host}/search`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${options.apiKey ?? ''}`,
},
body: JSON.stringify(body),
signal: options.signal,
})
if (!response.ok) {
throw new Error(`Web search failed with status ${response.status}`)
}
const payload = (await response.json()) as { results?: TavilyResponseItem[] }
const results = Array.isArray(payload.results) ? payload.results : []
// No link filtering: matches the old renderer Tavily provider, which returned every
// result Tavily sent (link-less items included) for the model to use.
const items = results.map((item) => ({
title: item.title ?? '',
link: item.url ?? '',
snippet: item.content ?? '',
}))
return maxResults !== undefined ? items.slice(0, maxResults) : items
}
/**
* Chatbox build-in search — single implementation behind the renderer's `build-in`
* provider (which injects an afetch `fetchFn` for retry + Chatbox error parsing, plus the
* Chatbox platform `headers`) and the native shell. `POST /api/tool/web-search`, licenseView on GitHub (pinned to 81571269ad)
Solutions
- Confirm options.apiKey is set, trimmed, and matches a valid Tavily key with remaining quota.
- Leave options.apiHost empty to use the default https://api.tavily.com, or ensure a custom host implements POST /search with Tavily's contract.
- Catch the error and fall back to another provider or return no results so the chat continues.
- On 429, surface 'quota exceeded' to the user rather than silently retrying.
- Strip whitespace/newlines from the key before storing it in settings.
Example fix
// before
const host = settings.apiHost
const items = await searchNativeTavily(query, { apiKey: settings.apiKey, apiHost: host })
// after
const apiKey = settings.apiKey.trim()
if (!apiKey) return []
try {
return await searchNativeTavily(query, { apiKey, apiHost: settings.apiHost })
} catch (e) {
console.warn('tavily search failed', e)
return []
} Defensive patterns
Strategy: validation
Validate before calling
// Block the call before it reaches Tavily when there is no usable key const apiKey = (settings.apiKey ?? '').trim() if (settings.provider === 'tavily' && !apiKey) return []
Try / catch
// Fall back to another provider on failure
try {
return await searchNativeTavily(query, { apiKey, apiHost, signal })
} catch (e) {
console.warn('tavily failed', e)
return []
} Prevention
- Trim the Tavily key on save to avoid whitespace/newline auth failures.
- Leave apiHost empty unless you are targeting a known Tavily-compatible endpoint.
- Watch free-tier usage; 429 means quota, not a bug.
- Prefer maxResults to bound both request size and response cost.
When it happens
Trigger: Tavily POST returns response.ok === false: 401 for missing/invalid apiKey (an empty key sends `Bearer `), 429 for quota/rate limit (Tavily free tier is small), 5xx outage, or a wrong apiHost override returning a non-2xx. Aborting options.signal mid-flight can also surface here.
Common situations: User picked Tavily without entering a key; free-tier quota exhausted after a few searches; options.apiHost customized to a wrong/mocked host that does not implement /search; Tavily regional block; key pasted with stray whitespace/newline.
Related errors
- Querit search failed with status ${response.status}
- No content extracted from file
- Failed to search knowledge base (id: ${kbId}). Please try ag
- Knowledge base name cannot be empty
- Failed to refresh token: missing tokens in response headers
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/a65cc0d920822d08.
Report an issue: GitHub.