{"record":{"id":"4af12c3add06e37a","repo":"chatboxai/chatbox","slug":"querit-search-failed-with-status-response-status","errorCode":null,"errorMessage":"Querit search failed with status ${response.status}","messagePattern":"Querit search failed with status (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/shared/services/native-web-search.ts","lineNumber":203,"sourceCode":"  const body: { query: string; count: number; filters?: { timeRange: { date: string } } } = {\n    query,\n    count: options.maxResults ?? 5,\n  }\n  if (timeRange) {\n    body.filters = { timeRange: { date: timeRange } }\n  }\n\n  const response = await fetchFn(QUERIT_SEARCH_URL, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      Authorization: `Bearer ${options.apiKey ?? ''}`,\n    },\n    body: JSON.stringify(body),\n    signal: options.signal,\n  })\n  if (!response.ok) {\n    throw new Error(`Querit search failed with status ${response.status}`)\n  }\n  const payload = (await response.json()) as {\n    error_code?: number\n    error?: unknown\n    results?: { result?: Array<{ title: string; url: string; snippet: string }> }\n  }\n  if (payload.error_code !== 200) {\n    // Keep the renderer's diagnostic: an HTTP 200 with a business error_code\n    // (e.g. invalid/expired key) otherwise yields zero results with no trace.\n    console.error('Querit search API error:', payload.error_code, payload.error)\n    return []\n  }\n  if (!payload.results?.result || !Array.isArray(payload.results.result)) {\n    return []\n  }\n  return payload.results.result.map((result) => ({\n    title: result.title,\n    link: result.url,","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/shared/services/native-web-search.ts#L185-L221","documentation":"Thrown by searchNativeQuerit (src/shared/services/native-web-search.ts:203) when POST https://api.querit.ai/v1/search returns a non-2xx status. The request sends Authorization: Bearer <apiKey> and { query, count, filters? }. Note the asymmetry: an HTTP 200 carrying a business error_code !== 200 does NOT throw (it logs and returns []); only transport-level failures (non-ok) throw here. So this error specifically means the HTTP layer rejected the request, most often an auth/key problem.","triggerScenarios":"Querit POST returns response.ok === false, e.g. 401/403 for an empty/invalid/expired apiKey, 429 for quota/rate limit, 5xx for Querit outage, or a network/TLS failure surfaced as a non-ok response. An empty options.apiKey produces `Bearer ` and typically yields 401.","commonSituations":"User selected the Querit provider but never entered an API key; the key expired or hit its quota; options.apiKey is whitespace (sent verbatim as the bearer token); Querit API changed its URL or auth scheme; corporate firewall/proxy returns a blocking status page.","solutions":["Verify a non-empty, valid Querit API key is configured (options.apiKey) and that the user's plan/quota is active.","Check options.signal is not already aborted before the call (an abort can surface as a failed fetch).","Treat 429/5xx as transient: catch and degrade to 'no results' or retry with backoff rather than crashing the chat flow.","Confirm reachability of https://api.querit.ai/v1/search from the runtime (mobile shell network, emulator, proxy).","If you need the business-level error detail, note this throw only carries the HTTP status; enable the existing console.error path for error_code diagnostics on 200 responses."],"exampleFix":"// before\nconst items = await searchNativeWeb(query, { provider: 'querit', apiKey })\n\n// after\nlet items: NativeWebSearchResultItem[] = []\ntry {\n  items = await searchNativeWeb(query, { provider: 'querit', apiKey })\n} catch (e) {\n  console.warn('querit search unavailable', e)\n}","handlingStrategy":"validation","validationCode":"// Use the shared config guard before invoking Querit\nif (!hasNativeWebSearchConfiguration({ provider: 'querit', apiKey }, licenseKey)) {\n  return [] // no valid key -> skip the failing call entirely\n}","typeGuard":null,"tryCatchPattern":"// Distinguish auth/quota from transient and degrade gracefully\ntry {\n  return await searchNativeWeb(query, { provider: 'querit', apiKey, signal })\n} catch (e) {\n  const msg = (e as Error).message\n  if (msg.includes('401') || msg.includes('403')) notifyInvalidKey()\n  return []\n}","preventionTips":["Require a non-empty, trimmed Querit key in settings before enabling the provider.","Remember HTTP 200 + business error_code returns [], not a throw; watch console.error for those diagnostics.","Forward options.signal so user cancellation does not look like a server failure.","Pre-check quota/plan limits with Querit if available rather than discovering 429 at call time."],"tags":["web-search","network","api","querit","auth"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}