Repository navigation
Closed as not planned
Description
Summary
Requests to Z.AI API (api.z.ai) fail with ECONNRESET after ~40-100 seconds when using the zai-coding-plan provider. The same API works correctly via curl and in other tools (e.g., OpenClaw via VPS proxy).
Environment
- OpenCode: v1.2.15
- Platform: macOS (arm64)
- Provider: zai-coding-plan
- Model: glm-5
- Endpoint:
https://api.z.ai/api/coding/paas/v4/chat/completions
Error Details
From ~/Library/Logs/ai.opencode.desktop/opencode-desktop_*.log:
ERROR service=llm providerID=zai-coding-plan modelID=glm-5 sessionID=ses_xxx small=false agent=build mode=primary
error={"error":{"code":"ECONNRESET","path":"https://api.z.ai/api/coding/paas/v4/chat/completions","errno":0}} stream error
Timing pattern of failures (from logs):
- Most failures occur after 39-100 seconds
- Some as long as 1000+ seconds
- 0 successful requests logged (101 ECONNRESET errors in one session)
Reproduction
- Configure
zai-coding-planprovider with a valid API key viaopencode auth login - Select
glm-5model - Send any prompt
- After ~40-100 seconds:
ECONNRESETerror
Verification that API works
Direct curl requests work fine:
curl -X POST "https://api.z.ai/api/coding/paas/v4/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <key>" \
-d '{"model":"glm-5","messages":[{"role":"user","content":"hi"}],"stream":true}'
# Returns streaming response successfullySame API also works when routed through a VPS proxy (tested with OpenClaw which proxies through a France VPS).
Analysis
The issue appears to be with Bun's HTTP client in the OpenCode sidecar:
- Bun's connection pooling: Bun aggressively reuses HTTP connections (keep-alive)
- Z.AI's idle timeout: Server likely closes idle connections after 30-60 seconds
- Race condition: When Bun tries to reuse a connection that the server has already closed →
ECONNRESET
The sidecar process (opencode-cli serve) makes the actual API calls:
/Applications/OpenCode.app/Contents/MacOS/opencode-cli --print-logs --log-level WARN serve --hostname 127.0.0.1 --port XXXXX
Suggested Fix
- Disable keep-alive for Z.AI endpoints, or
- Add retry logic with fresh connection on
ECONNRESET, or - Reduce connection pool lifetime for streaming endpoints
Workaround Attempts
- Setting
HTTPS_PROXYenvironment variable: doesn't help (sidecar is separate process) - Bun config (
~/.bunfig.toml): OpenCode binary appears to ignore it - VPN: issue persists regardless of network route
Related
- Z.AI documentation for OpenCode: https://docs.z.ai/integrations/opencode
Reacted by Quack, Ingo Kegel, William Derksen and Mikhail Emelyanov
Metadata
Metadata
Assignees
Labels
No labels
Activity
github-actions commentedon Feb 27, 2026
This issue might be a duplicate of existing issues. Please check:
lele872 commentedon May 31, 2026
Confirming this issue persists on v1.14.50 (latest) with the same
zai-coding-planprovider.Environment:
zai-coding-planglm-5.1What I am seeing:
The error appears intermittently in the desktop app UI as:
The retry logic kicks in and eventually recovers, but the user experience is poor — especially during long agent runs where this can happen multiple times per session. The error is not consistent; some requests succeed while others fail after ~30-60 seconds.
Verification that the API itself works fine:
Direct
curlrequests toapi.z.aiwork reliably with no disconnections:No proxy, no VPN, no firewall involved. The issue is isolated to the OpenCode sidecar.
Root cause analysis (from source code investigation):
I traced through the codebase and the flow is:
ECONNRESETpackages/llm/src/schema/errors.ts:118-128,TransportReason.retryablereturnsfalse, so the executor-level retry inpackages/llm/src/route/executor.ts:342-353does not retry the request with a fresh connectionpackages/opencode/src/session/message-v2.ts:636-648, which correctly marks it as retryable at the session level — but by then the same stale connection may be reused again, causing repeated failuresSuggested fix direction:
The most effective fix would be to make
TransportReasonretryable in the executor (with the existingMAX_RETRIES = 2cap), so ECONNRESET triggers an immediate retry with a new TCP connection before escalating to the session-level retry. This would catch the stale-connection case early and prevent the visible error loop.Alternatively, a custom fetch wrapper that sets
Connection: closefor providers known to have aggressive idle timeouts (or disables keep-alive pooling) would prevent the stale connection reuse entirely.Related issues and PRs I found:
verbose: truein the second argument to fetch() #21643 — same error messageHappy to help test any fix or provide more logs if needed.
github-actions commentedon Jul 31, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.