koala73/worldmonitor · error
P0 search failed: HTTP ${resp.status}
Error message
P0 search failed: HTTP ${resp.status} What it means
P0Provider.search() throws when POST {P0_BASE_URL}/search returns a non-2xx status. The search endpoint takes query, num_results (default 10) and include_domains with x-api-key auth. Unlike scrape, no fallback path is wired for search — Exa is the pipeline's primary search provider — so an HTTP failure here propagates straight to the caller.
Source
Thrown at consumer-prices-core/src/acquisition/p0.ts:82
markdown: data.markdown,
statusCode: data.statusCode ?? 200,
provider: this.name,
fetchedAt: new Date(),
};
}
async search(query: string, opts: SearchOptions = {}): Promise<SearchResult[]> {
const resp = await fetch(`${this.baseUrl}/search`, {
method: 'POST',
headers: this.headers(),
body: JSON.stringify({
query,
num_results: opts.numResults ?? 10,
include_domains: opts.includeDomains,
}),
});
if (!resp.ok) throw new Error(`P0 search failed: HTTP ${resp.status}`);
const data = (await resp.json()) as P0SearchResponse;
return (data.results ?? []).map((r) => ({
url: r.url,
title: r.title,
text: r.snippet,
}));
}
async validate(): Promise<boolean> {
try {
const resp = await fetch(`${this.baseUrl}/health`, {
headers: this.headers(),
signal: AbortSignal.timeout(5_000),
});
return resp.ok;
} catch {
return false;View on GitHub (pinned to eeab0a219f)
Solutions
- Map the status code to auth (401/403), quota/rate (402/429), or outage (5xx) and fix accordingly
- Verify P0_BASE_URL ends in the correct API version path
- Route search through Exa — the provider the pipeline is designed around — and keep P0 for scraping only
- Retry with backoff on 429/5xx before giving up
Example fix
// before
const results = await p0.search(query);
// after — retry transient statuses, fail fast on auth
const results = await retryOn(() => p0.search(query), {
retries: 2,
if: (e) => /HTTP (429|5\d\d)/.test(String(e?.message)),
}); Defensive patterns
Strategy: retry
Validate before calling
// probe the provider before relying on search
if (!(await p0.validate())) {
throw new Error('P0 /health failed — do not route search through it');
} Type guard
function isP0SearchHttpError(err: unknown): boolean {
return err instanceof Error && /^P0 search failed: HTTP \d+$/.test(err.message);
} Try / catch
try {
return await p0.search(q, opts);
} catch (err) {
if (isP0SearchHttpError(err) && /HTTP (429|5\d\d)/.test((err as Error).message)) {
await sleep(2_000);
return await p0.search(q, opts); // transient only
}
throw err; // 401/403/4xx is permanent — surface it
} Prevention
- Reserve P0 for scrape jobs; wire search to Exa, the provider the pipeline is designed around
- Health-check P0 via validate() before any run that calls search
- Alert on 429 clusters — they precede quota exhaustion
When it happens
Trigger: 401/403 invalid P0_API_KEY on /search; 429 when search quota is exhausted; 5xx during a P0 outage; P0_BASE_URL misconfigured so /search resolves to a wrong path or gateway.
Common situations: Using P0 for search without provisioning search on the plan; P0_API_KEY rotated but only some workers restarted; a gateway returning 502 between the worker and P0.
Related errors
- P0 scrape failed: HTTP ${resp.status}
- Exa search failed HTTP ${resp.status}: ${text.slice(0, 120)}
- Revoke failed (HTTP ${resp.status}).
- DNS ${recordType} lookup failed: status ${data.Status}
- Exa ${endpoint.slice(1)} failed HTTP ${response.status}: ${d
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/e2757c4de9cbee1d.
Report an issue: GitHub.