can1357/oh-my-pi · error · SearchProviderError
${err.message}
Error message
${err.message} What it means
Re-thrown by searchKagi as a SearchProviderError wrapping a KagiApiError whose statusCode is not classified by classifyProviderHttpError (i.e. an unexceptional or unusual HTTP status). The original Kagi error message is preserved verbatim.
Source
Thrown at packages/coding-agent/src/web/search/providers/kagi.ts:68
fetch: params.fetch,
},
params.authStorage,
);
return {
provider: "kagi",
sources: toSearchSources(result.sources, numResults),
relatedQuestions: result.relatedQuestions.length > 0 ? result.relatedQuestions : undefined,
requestId: result.requestId,
answer: result.answer,
};
} catch (err) {
if (err instanceof KagiApiError) {
if (typeof err.statusCode === "number") {
const classified = classifyProviderHttpError("kagi", err.statusCode, err.message);
if (classified) throw classified;
}
throw new SearchProviderError("kagi", err.message, err.statusCode);
}
throw err;
}
}
/** Search provider for Kagi web search. */
export class KagiProvider extends SearchProvider {
readonly id = "kagi";
readonly label = "Kagi";
isAvailable(authStorage: AuthStorage): boolean {
return authStorage.hasAuth("kagi");
}
search(params: SearchParamsWithFetch): Promise<SearchResponse> {
const fetchImpl = params.fetch;
return searchKagi({View on GitHub (pinned to 9690622007)
Solutions
- Read err.status (the wrapped statusCode) and err.message for the actual Kagi failure reason
- Check your Kagi API key balance/subscription if the message indicates payment or quota
- Retry with backoff for 5xx-class statuses
- Add the unclassified status to classifyProviderHttpError if it should map to a richer error
Example fix
// before
const results = await searchKagi({ query, authStorage });
// after
try {
const results = await searchKagi({ query, authStorage });
} catch (err) {
if (err instanceof SearchProviderError && err.status === 402) {
// Kagi subscription issue — check billing
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify Kagi key works with a cheap call
const ok = await fetch('https://kagi.com/api/v0/search?q=test', { headers: { Authorization: `Bot ${key}` } }).then(r => r.status !== 401); Type guard
function isKagiApiError(e: unknown): e is { name: 'KagiApiError'; statusCode?: number; message: string } {
return e instanceof Error && e.name === 'KagiApiError';
} Try / catch
try {
const res = await searchKagi({ query, authStorage });
} catch (err) {
if (err instanceof SearchProviderError && typeof err.status === 'number') {
if (err.status === 402) handleBilling();
else if (err.status >= 500) retryWithBackoff();
else throw err;
} else throw err;
} Prevention
- Keep the Kagi subscription funded/active
- Preflight the API key at startup
- Retry only 5xx-class statuses with exponential backoff
- Track unclassified status codes and extend classification as needed
When it happens
Trigger: Kagi API request fails with a KagiApiError carrying a numeric statusCode that classifyProviderHttpError does not map (e.g. 4xx/5xx statuses outside the classified set like 402, 418, 520), so the raw error is wrapped and thrown.
Common situations: Kagi billing/quota states (402 payment required), unusual upstream errors behind Kagi, novel status codes not yet in the classification table.
Related errors
- Devin AssignModel error ${response.status} ${response.status
- GitLab Duo Workflow create failed with HTTP ${response.statu
- ${response.status} ${response.statusText}: ${text}
- ${context}: ${response.status} ${response.statusText}${suffi
- HTTP ${response.status}: ${text}${suffix}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6ca6d1fe6df001cc.
Report an issue: GitHub.