What do you want to change?
isRetryableAssistantError (packages/ai/src/utils/retry.ts) does not classify bun's fetch socket-drop error as retryable, so pi terminates on a transient network drop without retrying once when running on the bun runtime.
Why?
Repro: pi --mode json on oven/bun:1-alpine, provider = tencentmaas (openai-compatible), mid-stream the upstream socket closes. The final message_end event:
stopReason: "error"
errorMessage: "The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()"
Result: willRetry=false, agent ends immediately, 0 retries. The retry settings are enabled (default maxRetries=3).
Root cause — RETRYABLE_PROVIDER_ERROR_PATTERN lists Node/undici wording ("socket hang up", "fetch failed", "other side closed") but not bun's wording. I confirmed by running the current regex against the error string: no match → classified non-retryable. On Node the same physical socket drop surfaces as "fetch failed" / "socket hang up" and does retry; on bun it surfaces as "socket connection was closed unexpectedly" and does not.
This silently fails long-running headless jobs — the pi process exits cleanly (exit 0) because the error was "handled", but no work was produced.
How?
Add one pattern to RETRYABLE_PROVIDER_ERROR_PATTERN in packages/ai/src/utils/retry.ts, in the network/fetch block alongside "socket hang up":
"socket connection was closed", // bun fetch wording (vs Node's "socket hang up" / "fetch failed")
Plus a test in packages/ai/test/retry.test.ts using the real error string above. Happy to open a PR if lgtm.
What do you want to change?
isRetryableAssistantError(packages/ai/src/utils/retry.ts) does not classify bun's fetch socket-drop error as retryable, so pi terminates on a transient network drop without retrying once when running on the bun runtime.Why?
Repro: pi
--mode jsononoven/bun:1-alpine, provider = tencentmaas (openai-compatible), mid-stream the upstream socket closes. The finalmessage_endevent:Result:
willRetry=false, agent ends immediately, 0 retries. The retry settings are enabled (default maxRetries=3).Root cause —
RETRYABLE_PROVIDER_ERROR_PATTERNlists Node/undici wording ("socket hang up","fetch failed","other side closed") but not bun's wording. I confirmed by running the current regex against the error string: no match → classified non-retryable. On Node the same physical socket drop surfaces as"fetch failed"/"socket hang up"and does retry; on bun it surfaces as"socket connection was closed unexpectedly"and does not.This silently fails long-running headless jobs — the pi process exits cleanly (exit 0) because the error was "handled", but no work was produced.
How?
Add one pattern to
RETRYABLE_PROVIDER_ERROR_PATTERNinpackages/ai/src/utils/retry.ts, in the network/fetch block alongside"socket hang up":Plus a test in
packages/ai/test/retry.test.tsusing the real error string above. Happy to open a PR iflgtm.