can1357/oh-my-pi · error · SearchProviderError
Ecosia search failed: ${message}
Error message
Ecosia search failed: ${message} What it means
Thrown as a SearchProviderError from the Ecosia HTML scraping provider when any unexpected exception occurs during the search request/parsing pipeline. It is a catch-all wrapper: the original error's message (network failure, HTML parse failure, etc.) is embedded into 'Ecosia search failed: <message>'. Timeouts and aborts are handled separately with dedicated codes, so this indicates a non-timeout, non-abort failure.
Source
Thrown at packages/coding-agent/src/web/search/providers/ecosia.ts:131
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;
}
/** Execute an Ecosia web search and parse the server-rendered result page. */View on GitHub (pinned to 9690622007)
Solutions
- Check outbound network connectivity to https://www.ecosia.org from the machine running the agent (curl -v https://www.ecosia.org).
- Read the embedded <message> for the root cause and fix that underlying issue (DNS, proxy, TLS).
- Switch to a JSON-API-based provider (DuckDuckGo, Brave, Tavily) which is less fragile than HTML scraping.
- Retry once after a short delay if the underlying message suggests a transient network fault.
Example fix
// before
const results = await search({ provider: "ecosia", query });
// after
try {
const results = await search({ provider: "ecosia", query });
} catch (e) {
if (e instanceof SearchProviderError && e.provider === "ecosia") {
const results = await search({ provider: "duckduckgo", query }); // fallback
} else throw e;
} Defensive patterns
Strategy: try-catch
Type guard
function isSearchProviderError(e: unknown): e is SearchProviderError {
return e instanceof SearchProviderError;
} Try / catch
try {
const res = await search({ provider: "ecosia", query });
} catch (e) {
if (e instanceof SearchProviderError && e.provider === "ecosia") {
// inspect e.message for the root cause; fall back to another provider
} else throw e;
} Prevention
- Verify outbound connectivity to ecosia.org before relying on this provider in deployments
- Prefer JSON-API providers (Brave, Tavily) over HTML scraping for production
- Add a fallback provider chain so single-provider failures degrade gracefully
- Monitor the embedded root-cause message to distinguish network vs markup changes
When it happens
Trigger: Any exception thrown inside callEcosiaHtml that is not a SearchProviderError and not an abort: fetch failing with connection reset/DNS failure, TLS errors, or the HTML result parser throwing on malformed markup. Signal aborted cases and timeouts are routed to other branches.
Common situations: Corporate proxies or firewalls resetting connections to ecosia.org; transient DNS failures; Ecosia changing its HTML markup so the scraper's extraction code throws; running in an environment without outbound network access.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Ecosia search timed out.
- Codex request failed (${code}): ${message || "Request failed
- DuckDuckGo HTML error (${page.status})
- Ecosia blocked the request with a Cloudflare bot challenge.
- Ecosia HTML error (${page.status})
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/9d5f4fcc3a80503e.
Report an issue: GitHub.