can1357/oh-my-pi · error · SearchProviderError
Ecosia search timed out.
Error message
Ecosia search timed out.
What it means
callEcosiaHtml wraps browserFetch of Ecosia's search page in a hard-timeout signal. If the underlying fetch or render-wait throws and neither the outer params.signal nor a prior SearchProviderError explains it, a signal.aborted check distinguishes timeouts: it throws a SearchProviderError with status 504 when the composed hard-timeout signal fired.
Source
Thrown at packages/coding-agent/src/web/search/providers/ecosia.ts:128
try {
page = await browserFetch(url.href, {
fetch: params.fetch,
signal,
timeoutMs: params.timeoutMs,
referer: ECOSIA_HOME_URL,
browser: {
homeUrl: ECOSIA_HOME_URL,
ready: {
selector: 'article[data-test-id="organic-result"]',
timeoutMs: RESULT_RENDER_TIMEOUT_MS,
},
shouldFallback: isBlockedPage,
},
});
} catch (error) {
if (error instanceof SearchProviderError || params.signal?.aborted) throw error;
if (signal.aborted) {
throw new SearchProviderError("ecosia", "Ecosia search timed out.", 504);
}
const message = error instanceof Error ? error.message : String(error);
throw new SearchProviderError("ecosia", `Ecosia search failed: ${message}`, 503);
}
if (isBlockedPage(page)) {
throw new SearchProviderError(
"ecosia",
"Ecosia blocked the request with a Cloudflare bot challenge. Ecosia's firewall throttles automated searches from datacenter/shared-egress IPs; try another web search provider such as DuckDuckGo, Brave, or Tavily.",
429,
);
}
if (page.status < 200 || page.status >= 300) {
const classified = classifyProviderHttpError("ecosia", page.status, page.html);
if (classified) throw classified;
throw new SearchProviderError("ecosia", `Ecosia HTML error (${page.status})`, page.status);
}
return page.html;View on GitHub (pinned to 9690622007)
Solutions
- Increase timeoutMs in the search params to accommodate Ecosia's JS render time.
- Retry — transient slowness often resolves; the provider chain may also fall back.
- Check network connectivity/latency to ecosia.com from the running environment.
- Switch to a faster or API-backed provider (Brave, Tavily) for latency-sensitive workloads.
Example fix
// before
await search({ provider: "ecosia", query, timeoutMs: 5000 }); // render wait exceeds 5s
// after
await search({ provider: "ecosia", query, timeoutMs: 20000 }); Defensive patterns
Strategy: retry
Validate before calling
// pre-call sanity: ensure the timeout budget is realistic
if (params.timeoutMs < 10000) console.warn("Ecosia HTML render typically needs >10s; low timeoutMs risks 504"); Type guard
function isEcosiaTimeout(e: unknown): e is SearchProviderError {
return e instanceof SearchProviderError && e.provider === "ecosia" && e.status === 504 && e.message === "Ecosia search timed out.";
} Try / catch
try {
return await searchEcosia(params);
} catch (e) {
if (isEcosiaTimeout(e)) return retryWithBackoff(() => searchEcosia({ ...params, timeoutMs: 20000 }));
if (e instanceof SearchProviderError && e.status === 429) return fallbackProvider(params);
throw e;
} Prevention
- Set timeoutMs generously (>=15s) for JS-rendered scrapers like Ecosia.
- Respect params.signal: caller aborts surface as-is, only internal hard timeouts become 504.
- Prefer API providers for latency-sensitive paths and keep scrapers as fallback.
When it happens
Trigger: browserFetch (including the result-render wait for `article[data-test-id="organic-result"]`) exceeds params.timeoutMs, aborting the withHardTimeout signal; the original error is then replaced by this 504 timeout error.
Common situations: Slow Ecosia page renders (Cloudflare interstitials delaying content); too-small timeoutMs passed in SearchParams; network latency to Ecosia; JS-render wait never matching the result selector after a page layout change.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- DuckDuckGo HTML error (${page.status})
- Ecosia search failed: ${message}
- Google browser search timed out.
- timed out: {command}
- AnthropicConnectionTimeoutError
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/290ad1aea1f5e5bb.
Report an issue: GitHub.