can1357/oh-my-pi · error · SearchProviderError

Ecosia HTML error (${page.status})

Error message

Ecosia HTML error (${page.status})

What it means

Generic non-2xx HTTP status from the Ecosia HTML endpoint that was not classified into a more specific provider error. The provider first tries classifyProviderHttpError for a richer message; if that returns nothing, it throws this with the raw status code as both message and status.

Source

Thrown at packages/coding-agent/src/web/search/providers/ecosia.ts:144

		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. */
export async function searchEcosia(params: SearchParams): Promise<SearchResponse> {
	const numResults = clampNumResults(params.numSearchResults ?? params.limit, DEFAULT_NUM_RESULTS, MAX_NUM_RESULTS);
	const html = await callEcosiaHtml(params);
	const parsed = parseHtmlResults(html);

	const sources: SearchSource[] = [];
	const seen = new Set<string>();
	for (const result of parsed) {
		if (seen.has(result.url)) continue;
		seen.add(result.url);
		sources.push({ title: result.title, url: result.url, snippet: result.snippet });
		if (sources.length >= numResults) break;
	}

View on GitHub (pinned to 9690622007)

Solutions

  1. Check Ecosia service status — a 5xx indicates a server-side problem on Ecosia's side.
  2. Retry with backoff; transient 502/503 responses usually resolve on their own.
  3. Switch to another search provider while Ecosia is degraded.
  4. Inspect the status code in the message to distinguish client (4xx) vs server (5xx) issues.
Defensive patterns

Strategy: retry

Try / catch

try {
  const res = await search({ provider: "ecosia", query });
} catch (e) {
  if (e instanceof SearchProviderError && e.status >= 500) {
    await Bun.sleep(1000); // retry with backoff for transient server errors
  } else throw e;
}

Prevention

When it happens

Trigger: Ecosia returned an HTTP status outside 200-299 (e.g. 500, 502, 503) and classifyProviderHttpError had no specific classification for that status/body combination.

Common situations: Ecosia server-side outages or maintenance; intermediate proxy/CDN errors (502/504); unexpected 4xx statuses not covered by the classifier.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f588205b89af9a83. Report an issue: GitHub.