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
- Retry the request — this is often transient infrastructure behavior
- Check any custom fetch/proxy passed via params.fetch for behavior that drops bodies
- Bypass interfering proxies or TLS-intercepting middlewares
- 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
- Avoid custom fetch wrappers that can return bodyless Responses
- Test through the same proxies/middleboxes used in production
- Retry transiently at the call site
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
- Devin API error: response body is empty
- Perplexity API error (${status}): ${details}
- Perplexity ask stream error: ${message}
- V2 compaction stream closed before response.completed
- stream ended before message_start
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/bb9e2932f9354578.
Report an issue: GitHub.