can1357/oh-my-pi · error · SearchProviderError
Perplexity API error (${status}): ${details}
Error message
Perplexity API error (${status}): ${details} What it means
throwPerplexityStreamError converts a failed assistant stream message from the Perplexity API-key (or OpenRouter) path into a thrown error. It first tries classifyProviderHttpError for a typed classification; if unclassified it throws a SearchProviderError for provider "perplexity" with a message embedding the HTTP-like status and error details reported on the stream message.
Source
Thrown at packages/coding-agent/src/web/search/providers/perplexity.ts:498
async function drainAssistantStream(stream: AssistantMessageEventStream): Promise<AssistantMessage> {
let finalMessage: AssistantMessage | undefined;
for await (const event of stream) {
if (event.type === "done") {
finalMessage = event.message;
} else if (event.type === "error") {
finalMessage = event.error;
}
}
return finalMessage ?? stream.result();
}
function throwPerplexityStreamError(message: AssistantMessage): never {
const status = message.errorStatus ?? 500;
const details = message.errorMessage ?? "Perplexity API stream failed";
const classified = classifyProviderHttpError("perplexity", status, details);
if (classified) throw classified;
throw new SearchProviderError("perplexity", `Perplexity API error (${status}): ${details}`, status);
}
/** Call Perplexity API-key endpoint (or OpenRouter) through the shared OpenAI streaming providers. */
async function callPerplexityApi(
config: ApiConfig,
request: PerplexityRequest,
fetchImpl: FetchImpl | undefined,
signal?: AbortSignal,
timeoutMs?: number,
): Promise<SearchResponse> {
const metadata: PerplexityApiStreamMetadata = {};
const context = buildPerplexityContext(request);
const requestSignal = withHardTimeout(signal, timeoutMs);
const onSseEvent = (event: { data: string }): void => {
collectPerplexityMetadata(metadata, event.data);
};
const message = config.useResponsesView on GitHub (pinned to 9690622007)
Solutions
- Read the status and details embedded in the message to identify the upstream cause
- Verify the Perplexity API key and remaining credits
- If 429/402, wait or top up credits before retrying
- Retry with a supported model name if the model was rejected
Defensive patterns
Strategy: try-catch
Validate before calling
if (!process.env.PERPLEXITY_API_KEY) throw new Error('Perplexity API key missing'); Type guard
function isSearchProviderError(e: unknown): e is SearchProviderError {
return e instanceof SearchProviderError;
} Try / catch
try {
return await perplexitySearch(params);
} catch (err) {
if (err instanceof SearchProviderError && /Perplexity API error \((\d+)\)/.test(err.message)) {
const status = Number(err.message.match(/\((\d+)\)/)?.[1]);
if (status === 429 || status === 402) await retryLater();
}
throw err;
} Prevention
- Monitor Perplexity credit balance before bulk searches
- Pin supported model names
- Surface stream failures to users with the embedded status code
When it happens
Trigger: callPerplexityApi's OpenAI-compatible streaming call ends with an error AssistantMessage (message.errorStatus set) — HTTP auth failure, quota exhaustion, invalid model/parameter, or mid-stream server error.
Common situations: Invalid or revoked Perplexity API key, exceeding monthly credits, requesting an unavailable model, OpenRouter key with insufficient balance.
Related errors
- Perplexity ask API error (${response.status}): ${errorText}
- parallel: err.message (dynamic; thrown as SearchProviderErro
- Perplexity ask API returned no response body
- Perplexity ask stream error: ${message}
- V2 remote compaction failed (${response.status} ${response.s
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d03305ec0dafa1ee.
Report an issue: GitHub.