can1357/oh-my-pi · error · SearchProviderError
Perplexity ask stream error: ${message}
Error message
Perplexity ask stream error: ${message} What it means
While consuming the Perplexity ask SSE stream, an event carried an error_code field, meaning Perplexity aborted the answer mid-stream. The provider throws a SearchProviderError (status 400) whose message is the stream's error_message, or the raw error_code when no human-readable message was supplied.
Source
Thrown at packages/coding-agent/src/web/search/providers/perplexity.ts:749
`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) {
answer = eventAnswer;
}
for (const source of buildOAuthSources(mergedEvent)) {
sourcesByUrl.set(oauthSourceKey(source.url), source);
}
const reportedModel = [mergedEvent.user_selected_model, mergedEvent.display_model].find(
candidate => candidate && candidate !== "turbo",
);
if (reportedModel) model = reportedModel;
if (mergedEvent.uuid) finalRequestId = mergedEvent.uuid;
if (mergedEvent.final || mergedEvent.status === "COMPLETED") {View on GitHub (pinned to 9690622007)
Solutions
- Read error_code/error_message in the message to identify the cause
- If auth-related, refresh the Perplexity OAuth token or supply valid cookies
- Rephrase or simplify the query if it was rejected by filters
- Retry; mid-stream upstream failures are often transient
Defensive patterns
Strategy: try-catch
Validate before calling
// verify a fresh session exists before streaming
if (!hasFreshOAuthSession("perplexity")) await loginPerplexityOAuth(); 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 && err.message.includes("ask stream error")) {
// auth codes -> re-login; otherwise transient -> retry or fall back
}
throw err;
} Prevention
- Keep OAuth sessions refreshed
- Avoid queries likely to trip content filters in automated pipelines
- Always have a non-streaming or alternate provider fallback
When it happens
Trigger: readSseJson yields a PerplexityOAuthStreamEvent with error_code set during callPerplexityAsk's for-await loop — e.g. invalid/expired OAuth token, query rejected by moderation, or upstream processing failure.
Common situations: Expired Perplexity OAuth access token, anonymous access blocked, queries that trip Perplexity's content filters, transient upstream model failures mid-stream.
Related errors
- V2 compaction stream closed before response.completed
- stream ended before message_start
- SSE stream ended without a resumable event ID
- Perplexity API error (${status}): ${details}
- Perplexity ask API error (${response.status}): ${errorText}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/4d64750ba2cf0292.
Report an issue: GitHub.