can1357/oh-my-pi · error · SearchProviderError

Perplexity ask API error (${response.status}): ${errorText}

Error message

Perplexity ask API error (${response.status}): ${errorText}

What it means

The Perplexity ask (OAuth/cookie) endpoint returned a non-ok HTTP response. The body text is captured, offered to classifyProviderHttpError, and otherwise thrown as a SearchProviderError including the response status and the raw error body.

Source

Thrown at packages/coding-agent/src/web/search/providers/perplexity.ts:729

	};

	// The consumer ask endpoint intermittently drops the socket before sending an
	// HTTP response (#5315). Retry the transport exactly once; once we hold an
	// HTTP response (handled below) the outcome — including non-2xx — is final and
	// never retried, so a real 401/429 is never papered over by a second attempt.
	let response: Response;
	try {
		response = await (params.fetch ?? fetch)(PERPLEXITY_OAUTH_ASK_URL, requestInit);
	} catch (error) {
		if (params.signal?.aborted) throw error;
		response = await (params.fetch ?? fetch)(PERPLEXITY_OAUTH_ASK_URL, requestInit);
	}

	if (!response.ok) {
		const errorText = await response.text();
		const classified = classifyProviderHttpError("perplexity", response.status, errorText);
		if (classified) throw classified;
		throw new SearchProviderError(
			"perplexity",
			`Perplexity ask API error (${response.status}): ${errorText}`,
			response.status,
		);
	}

	if (!response.body) {
		throw new SearchProviderError("perplexity", "Perplexity ask API returned no response body", 500);
	}

	let answer = "";
	let model: string | undefined;
	let finalRequestId: string | undefined;
	const sourcesByUrl = new Map<string, SearchSource>();
	let mergedEvent: PerplexityOAuthStreamEvent = { blocks: [] };

	for await (const event of readSseJson<PerplexityOAuthStreamEvent>(response.body, params.signal)) {
		if (event.error_code) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect response.status embedded in the message; 401/403 -> re-authenticate (refresh OAuth token or provide cookies)
  2. If 429, back off and retry later
  3. If 5xx, retry after a delay or check Perplexity status
  4. Fall back to a different search provider for this query
Defensive patterns

Strategy: retry

Validate before calling

// ensure an auth path exists before calling
const hasAuth = Boolean(process.env.PERPLEXITY_API_KEY) || hasStoredOAuthSession();

Type guard

function isSearchProviderError(e: unknown): e is SearchProviderError {
  return e instanceof SearchProviderError;
}

Try / catch

try {
  return await perplexityAsk(params);
} catch (err) {
  if (err instanceof SearchProviderError && /status (401|403)/.test(err.message)) {
    await refreshOAuthSession(); // re-authenticate once, then retry
  }
  throw err;
}

Prevention

When it happens

Trigger: callPerplexityAsk's fetch of the ask API returns response.ok === false — e.g. expired OAuth access token (401), CSRF/cookie failure (403), rate limiting (429), or Perplexity server errors (5xx).

Common situations: Stale or revoked Perplexity OAuth session, anonymous-mode IP blocked/challenged by Perplexity, per-account rate limits, Perplexity outages.

Related errors


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