can1357/oh-my-pi · error · SearchProviderError

Perplexity ask API returned no response body

Error message

Perplexity ask API returned no response body

What it means

After a successful (2xx) HTTP response from the Perplexity ask API, the response carried no readable body stream, so the SSE event stream cannot be consumed. The provider throws a SearchProviderError with status 500 to signal an unexpected empty response from the server.

Source

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

		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) {
			const message = event.error_message ?? event.error_code;
			throw new SearchProviderError("perplexity", `Perplexity ask stream error: ${message}`, 400);
		}

		mergedEvent = mergeOAuthEventSnapshot(mergedEvent, event);

		const eventAnswer = buildOAuthAnswer(mergedEvent);
		if (eventAnswer.length > 0) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry the request — this is often transient infrastructure behavior
  2. Check any custom fetch/proxy passed via params.fetch for behavior that drops bodies
  3. Bypass interfering proxies or TLS-intercepting middlewares
  4. Fall back to an alternate provider if it reproduces consistently
Defensive patterns

Strategy: retry

Try / catch

try {
  return await perplexityAsk(params);
} catch (err) {
  if (err instanceof SearchProviderError && err.message.includes("no response body")) {
    return await withRetry(() => perplexityAsk(params), { attempts: 2 });
  }
  throw err;
}

Prevention

When it happens

Trigger: fetch to the Perplexity ask endpoint resolves ok but response.body is null — happens with some proxies/mocks, certain HTTP/1.1 empty-body responses, or runtimes where streaming bodies are unavailable.

Common situations: Corporate proxy stripping/short-circuiting responses, custom fetch implementations (e.g. testing mocks) that return bodies-less Response objects, middleboxes returning empty 200s.

Related errors


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