can1357/oh-my-pi · error · SearchProviderError

Google HTML error (${page.status})

Error message

Google HTML error (${page.status})

What it means

Thrown by callGoogleHtml when the loaded page's HTTP status is outside 200–299 and the response was not already classified as a traffic challenge. The status code is included in the message and reused as the error status, indicating Google's server rejected the request in a way not covered by the specific block detectors.

Source

Thrown at packages/coding-agent/src/web/search/providers/google.ts:153

	} catch (error) {
		if (error instanceof SearchProviderError || params.signal?.aborted) throw error;
		if (signal.aborted) {
			throw new SearchProviderError("google", "Google browser search timed out.", 504);
		}
		const message = error instanceof Error ? error.message : String(error);
		throw new SearchProviderError("google", `Google browser search failed: ${message}`, 503);
	}

	const blocked = blockReason(page);
	if (blocked === "traffic") {
		throw new SearchProviderError(
			"google",
			"Google blocked the browser search with an automated-traffic challenge. Try another web search provider or retry later.",
			429,
		);
	}
	if (page.status < 200 || page.status >= 300) {
		throw new SearchProviderError("google", `Google HTML error (${page.status})`, page.status);
	}
	if (blocked === "javascript") {
		throw new SearchProviderError(
			"google",
			"Google returned its JavaScript challenge instead of rendered search results.",
			429,
		);
	}
	return page.html;
}

/** Execute a Google web search with fetch-first loading and a headless-browser fallback. */
export async function searchGoogle(params: SearchParams): Promise<SearchResponse> {
	const numResults = clampNumResults(params.numSearchResults ?? params.limit, DEFAULT_NUM_RESULTS, MAX_NUM_RESULTS);
	const html = await callGoogleHtml(params, numResults);
	const parsed = parseHtmlResults(html);

	const sources: SearchSource[] = [];

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the status code in the message for the specific failure class.
  2. Retry — 5xx statuses are typically transient.
  3. Update the omp package: Google's scraping endpoint behavior changes over time and fixes ship in newer versions.
  4. Fall back to an API-backed search provider for reliability.
Defensive patterns

Strategy: retry

Try / catch

try {
  return await search({ provider: 'google', query });
} catch (err) {
  const status = err instanceof SearchProviderError ? err.statusCode : undefined;
  if (status && status >= 500) return await retryWithBackoff(() => search({ provider: 'google', query }));
  throw err;
}

Prevention

When it happens

Trigger: The Google Search HTML fetch completes with a non-2xx status (e.g. 301/302 to an unresolvable redirect, 404, 5xx) while blockReason() returned undefined (not 403/429, no /sorry/ URL, no captcha markers).

Common situations: Google serving regional redirect loops or unexpected status codes; transient Google server errors; middleware/proxy rewriting the response; Google changing endpoint behavior after an update.

Related errors


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