{"record":{"id":"4d64750ba2cf0292","repo":"can1357/oh-my-pi","slug":"perplexity-ask-stream-error-message","errorCode":null,"errorMessage":"Perplexity ask stream error: ${message}","messagePattern":"Perplexity ask stream error: (.+?)","errorType":"exception","errorClass":"SearchProviderError","httpStatus":400,"severity":"error","filePath":"packages/coding-agent/src/web/search/providers/perplexity.ts","lineNumber":749,"sourceCode":"\t\t\t`Perplexity ask API error (${response.status}): ${errorText}`,\n\t\t\tresponse.status,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new SearchProviderError(\"perplexity\", \"Perplexity ask API returned no response body\", 500);\n\t}\n\n\tlet answer = \"\";\n\tlet model: string | undefined;\n\tlet finalRequestId: string | undefined;\n\tconst sourcesByUrl = new Map<string, SearchSource>();\n\tlet mergedEvent: PerplexityOAuthStreamEvent = { blocks: [] };\n\n\tfor await (const event of readSseJson<PerplexityOAuthStreamEvent>(response.body, params.signal)) {\n\t\tif (event.error_code) {\n\t\t\tconst message = event.error_message ?? event.error_code;\n\t\t\tthrow new SearchProviderError(\"perplexity\", `Perplexity ask stream error: ${message}`, 400);\n\t\t}\n\n\t\tmergedEvent = mergeOAuthEventSnapshot(mergedEvent, event);\n\n\t\tconst eventAnswer = buildOAuthAnswer(mergedEvent);\n\t\tif (eventAnswer.length > 0) {\n\t\t\tanswer = eventAnswer;\n\t\t}\n\t\tfor (const source of buildOAuthSources(mergedEvent)) {\n\t\t\tsourcesByUrl.set(oauthSourceKey(source.url), source);\n\t\t}\n\n\t\tconst reportedModel = [mergedEvent.user_selected_model, mergedEvent.display_model].find(\n\t\t\tcandidate => candidate && candidate !== \"turbo\",\n\t\t);\n\t\tif (reportedModel) model = reportedModel;\n\t\tif (mergedEvent.uuid) finalRequestId = mergedEvent.uuid;\n\t\tif (mergedEvent.final || mergedEvent.status === \"COMPLETED\") {","sourceCodeStart":731,"sourceCodeEnd":767,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/web/search/providers/perplexity.ts#L731-L767","documentation":"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.","triggerScenarios":"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.","commonSituations":"Expired Perplexity OAuth access token, anonymous access blocked, queries that trip Perplexity's content filters, transient upstream model failures mid-stream.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify a fresh session exists before streaming\nif (!hasFreshOAuthSession(\"perplexity\")) await loginPerplexityOAuth();","typeGuard":"function isSearchProviderError(e: unknown): e is SearchProviderError {\n  return e instanceof SearchProviderError;\n}","tryCatchPattern":"try {\n  return await perplexityAsk(params);\n} catch (err) {\n  if (err instanceof SearchProviderError && err.message.includes(\"ask stream error\")) {\n    // auth codes -> re-login; otherwise transient -> retry or fall back\n  }\n  throw err;\n}","preventionTips":["Keep OAuth sessions refreshed","Avoid queries likely to trip content filters in automated pipelines","Always have a non-streaming or alternate provider fallback"],"tags":["network","streaming","sse","perplexity","auth"],"backgroundTag":"sse-stream-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}