Repository navigation
Description
Summary
While the app server is running (opencode serve --service), changing the local IP of the host's active network interface (e.g., switching NetworkManager connection profiles on the same NIC) leaves the provider connections bound to the previous source IP. The sockets stay in ESTAB but are effectively blackholed, no new connections are opened, provider requests hang indefinitely and no error is logged. Restarting the app fixes it immediately.
Environment
- opencode version: v2.0.16
- OS: Ubuntu 24.10, Linux 6.14.6-061406-generic (x86_64)
- Terminal: xterm-256color (truecolor), no
TERM_PROGRAMreported - Shell: /bin/bash
- Install/channel: official binary (
~/.opencode/bin/opencode), latest - Active plugins: none
Reproduction
- Start opencode while the machine has
OLD_IPon the active interface (e.g., a DHCP profile). The server establishes long-lived connections to the provider (e.g.,opencode.ai:443,models.opencode.ai:443). - Without stopping opencode, switch the same interface to a different profile that assigns
NEW_IP(e.g.,nmcli con up <static-profile>), or otherwise change the interface address. - Inspect the server sockets with
ss -tnp | grep opencode. They still showOLD_IP:<port> -> provider:443 (ESTAB), whileip addrshowsNEW_IPon the interface. No new connections are opened, even after 15+ seconds. - Send a chat message / trigger any provider request. It hangs. The log shows no
WARN/ERRORentries during the hang and no user-visible error is surfaced. - Switch back to the original profile (
OLD_IPreturns): pending requests resume without restarting the app.
Immediate workaround: fully restart the app (or the service process). After that, ss shows the connections re-established from NEW_IP and provider requests succeed.
Expected Behavior
- The app should detect network/interface address changes and re-establish provider connections using the current source address.
- At minimum it should fail fast (short connect/read timeouts or TCP keepalive) and surface an error instead of hanging indefinitely.
Actual Behavior
- Existing provider sockets remain bound to the previous IP and continue to be used after the host address changes. Requests hang silently with no log output and no reconnect. Only restarting the app (or restoring the old IP) recovers it.
Additional Context
-
Network connectivity itself is fine during the hang: from the same host and interface,
curlto the provider endpoints succeeds with a valid TLS chain and HTTP 200 (opencode.ai,models.opencode.ai,/zen/v1/...), and DNS resolution is correct. Only the already-running app instance is affected. -
Consistently reproducible across repeated profile switches on the same NIC.
-
Appears to affect both the background service and the client: after a restart, new connections from the current IP appear for both processes.
-
Sanitized
ssoutput captured while the hang was active (interface already hadNEW_IP):ESTAB 0 0 OLD_IP:PORT provider:443 users:(("opencode",pid=...,fd=24)) ESTAB 0 0 OLD_IP:PORT provider:443 users:(("opencode",pid=...,fd=25)) -
No errors in the app log during the hang; periodic
provider.updated/model.updatedevents only appear once connectivity is valid again. -
Suggestion: subscribe to netlink address-change events (or NetworkManager D-Bus signals) and reset the provider connection pool; additionally add connection timeouts/keepalives so a stale pooled socket fails fast and can be retried with the current source address.
Activity
github-actions commentedon Oct 5, 2026
This issue might be a duplicate of an existing issue. Please check:
opencode servefailing to recover after a network change until the server process is restarted. That report is MCP-specific, but the network-change and stale-connection behavior is similar.opencodejr commentedon Oct 27, 2026
Thanks for the detailed report. I can reproduce this on v2.0.16 and on the latest
dev(f7d0ce1), using a local mock provider instead of opencode.ai.What I did:
opencode serveand sent one prompt. It works, andssshows a pooled keep-alive socket from the original address.ip addr delthe old one,ip addr adda new one).curlto the provider from the new address still works.What I saw:
v2.0.16 has no transport timeout, so the hang there should last indefinitely. Current
devhas a default 5-minute response-header timeout, so the request probably fails and retries after about 5 minutes, but I didn't confirm that. Either way the stale socket isn't detected and the prompt hangs silently for minutes.The script below reproduces it (it needs root for the network namespace). Related issues: #53747 (steps stalling with no timeout) and #52866 (stall timeout and keepalive handling).
Reproduction script (repro.sh)
Run it:
bash repro.sh