[llm-pi-ai] Wire finish_reason "network_error" classifies as PI_AI_ERROR and defeats dsh-llm-retry's default retry #4361
yangwuan55
started this conversation in
General
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Some OpenAI-compatible relays terminate a stream with a non-standard wire
finish_reason: "network_error"instead of closing the connection. pi-ai's OpenAI-completions adapter already special-cases unknown finish reasons into{ stopReason: 'error', errorMessage: 'Provider finish_reason: <reason>' }, so dsh receives the terminal messageProvider finish_reason: network_error.But
classifyPiAiError()fails to recognize that text, so the failure falls through to the catch-allPI_AI_ERRORcode — which is not indsh-llm-retry's default normal-mode retryable set. Result: a transient network failure becomes a terminal turn error with zero automatic recovery.Repro
\bnetwork\bcannot match"network_error"because_is a\wcharacter: there is no word boundary betweenkand_, so the trailing\bafternetworkfails.Failure chain
finish_reason: "network_error"{ stopReason: "error", errorMessage: "Provider finish_reason: network_error" }classifyPiAiError()(packages/llm/llm-pi-ai/src/stream.ts) returns catch-allPI_AI_ERRORdsh-llm-retrynormal mode retries onlyEMPTY_RESPONSE / RATE_LIMIT / SERVER / TIMEOUT / TRANSPORT→ delegates without retrying{ kind: 'retry' }onagent/request-error→LlmErroris terminalObserved live on dsh 0.1.0-rc.8 behind an
openai-completionsprovider: the turn ends withreason.kind === 'error'carrying exactly this message, and nollm/retryevents are ever recorded.Impact
Any flaky relay that surfaces connection problems as wire
finish_reason: network_errorhard-fails turns with no automatic recovery, even though the failure is transient by nature. Users can work around it per-provider today via:…but that also whitelists genuinely permanent unknown errors, which is why the default set should classify this correctly at the source.
Suggested fix
Extend the transport family so punctuated variants match (
src/stream.ts,classifyPiAiError):This keeps plain
networkmatching and additionally coversnetwork_error,connection error, etc. I understand the XXX comment above the function prefers cause/code-based classification once pi-ai forwards original errors — this is only the minimal text-level stopgap, consistent with the existing wording list.Regression test: add
'Provider finish_reason: network_error'to theit.eachtransport-cases table inpackages/llm/llm-pi-ai/tests/convert.spec.ts.All reactions