You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
opencode2 became stuck starting its managed background server #41696
opencode2 became stuck starting its managed background server. It repeatedly spawned serve --service, but never reported the underlying error.
Plugins
No response
OpenCode version
OpenCode: 0.0.0-next-17090
Steps to reproduce
The managed service was configured to use port 49374, which was already occupied by Ollama.
Running the server directly exposed the otherwise hidden error:
Managed service port 49374 on 127.0.0.1 is already in use by another process.
Configure another port with opencode service set port <port> and start the service again.
opencode2 service start should surface the port-conflict error immediately rather than silently spawning repeated serve --service attempts.
If your issue is distinct (e.g. specific to the managed service / opencode2 service start flow rather than opencode serve directly), feel free to clarify and we can keep it open as a separate tracking item.
Addressed by #41793. Managed service contenders now retain a bounded stderr tail and append it to nonzero-exit/signal startup failures, so port conflicts surface the existing actionable remediation instead of only Server process exited with code 1. Effect, Promise, and real CLI boundary regressions cover the behavior. Closing as resolved on the v2 branch.
Reproduced a remaining form of this on 0.0.0-beta-17498, after #41793.
Port 49374 was occupied by an unregistered older opencode2 serve --service process. Plain opencode2 repeatedly spawned contenders and eventually returned:
Timed out waiting for the background service to start
The likely remaining gap is contender overlap: recognizeIncumbent can take 15 seconds, while Service.ensure keeps up to two contenders. A finished contender’s captured failure is returned only when no other contender remains. When another contender is still running, that failure is removed and discarded. This can repeat until the overall timeout, hiding the stderr added by #41793.
Stopping the old listener immediately restored normal managed startup.
Environment: Fedora Linux 44 x86_64, OpenCode 0.0.0-beta-17498.
timestamp=2026-08-26T14:25:53.050Z level=INFO run=e15c8c4d message="cli starting" version=0.0.0-beta-18155 channel=beta local=false args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:25:57.834Z level=ERROR run=2f998337 message="cli process failed" cause="Cause([Fail(Error: Managed service port 49374 on 127.0.0.1 is already in use by another process. Configure another port with `opencode service set port <port>` and start the service again. (cause: ServeError (cause: Error: Failed to start server. Is port 49374 in use?)))])" args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:25:58.158Z level=INFO run=3973746d message="cli starting" version=0.0.0-beta-18155 channel=beta local=false args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:26:08.486Z level=ERROR run=e15c8c4d message="cli process failed" cause="Cause([Fail(Error: Managed service port 49374 on 127.0.0.1 is already in use by another process. Configure another port with `opencode service set port <port>` and start the service again. (cause: ServeError (cause: Error: Failed to start server. Is port 49374 in use?)))])" args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:26:09.152Z level=INFO run=d041c690 message="cli starting" version=0.0.0-beta-18155 channel=beta local=false args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:26:13.622Z level=ERROR run=3973746d message="cli process failed" cause="Cause([Fail(Error: Managed service port 49374 on 127.0.0.1 is already in use by another process. Configure another port with `opencode service set port <port>` and start the service again. (cause: ServeError (cause: Error: Failed to start server. Is port 49374 in use?)))])" args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:26:13.988Z level=INFO run=3a268f39 message="cli starting" version=0.0.0-beta-18155 channel=beta local=false args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:26:16.071Z level=ERROR run=34997653 message="cli process failed" cause="Cause([Fail(Error: Timed out waiting for the background service to start)])" args="[\"-c\"]" role=cli
timestamp=2026-08-26T14:26:24.660Z level=ERROR run=d041c690 message="cli process failed" cause="Cause([Fail(Error: Managed service port 49374 on 127.0.0.1 is already in use by another process. Configure another port with `opencode service set port <port>` and start the service again. (cause: ServeError (cause: Error: Failed to start server. Is port 49374 in use?)))])" args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-08-26T14:26:29.471Z level=ERROR run=3a268f39 message="cli process failed" cause="Cause([Fail(Error: Managed service port 49374 on 127.0.0.1 is already in use by another process. Configure another port with `opencode service set port <port>` and start the service again. (cause: ServeError (cause: Error: Failed to start server. Is port 49374 in use?)))])" args="[\"serve\",\"--service\"]" role=cli
opencdoe2 then does not start. but nothing is using that port: lsof -nP -iTCP:49374 -sTCP:LISTEN shows nothing
Still reproducible on opencode2 v0.0.0-beta-19242 on macOS arm64.
Running opencode2 repeatedly tried to start the background server, then returned:
Starting background server...
Error: Timed out waiting for the background service to start
The log at ~/.local/share/opencode/log/opencode.log and running opencode2 serve --service --print- logs --log-level debug exposed the underlying error:
Managed service port 49374 on 127.0.0.1 is already in use by another process.
lsof -nP -iTCP:49374 showed nothing, but netstat -anv -p tcp | rg 49374 showed macOS’s symptomsd listening on *.49374. A separate socket bind test confirmed “Address already in use.”
Switching to a free port restored startup:
opencode2 service set port 49375
opencode2 service start
Confirmed the service was listening on 127.0.0.1:49375. The remaining problem is that the CLI still
hides the actionable port-conflict error behind a generic timeout.
Reproduced on the release channel, opencode v2.0.3 (macOS 26 / Darwin 27, arm64, bun global install) — so this has shipped to stable, not just next/beta.
Root cause confirmed in code (v2 branch):
packages/cli/src/server-process.ts:149 — the spawned serve --service correctly detects EADDRINUSE and produces the actionable message, including the service set port hint.
packages/client/src/effect/service.ts:122 — a finished contender's failure is returned only when contenders.size === 0. Because the ensure loop keeps one candidate plus one lock probe in flight, each failure arrives while another contender is still pending, so the specific error is dropped every iteration; line 138 then throws the generic Timed out waiting for the background service to start with no cause. Same pattern in packages/client/src/promise/service.ts:59.
Suggested fix: retain the most recent contender failure and attach it as cause to the final timeout error.
One extra data point on how the port gets poisoned with no visible listener: in my case lsof -nP -iTCP:49374 -sTCP:LISTEN showed nothing, and a manual Python bind() with SO_REUSEADDR still failed with EADDRINUSE. The culprit was a stale ESTABLISHED loopback connection, 127.0.0.1:49383 -> 127.0.0.1:49374, held by the Tailscale GUI app (no tailscale serve/funnel config — a coincidental ephemeral-range collision; the hidden peer end was likely a root-owned process, invisible to user-level lsof). On Darwin, SO_REUSEADDR only permits rebinding when prior sockets are in TIME_WAIT; an active socket with that local port blocks bind() regardless. Quitting Tailscale closed the connection and the managed service started immediately and healthily.
So "nothing is listening on the port" does not rule out this failure mode — lsof -nP -iTCP:<port>without the LISTEN filter (or netstat -an) is needed, which makes the missing error message even more costly.
(Full environment and log excerpts in #49009, closed as a duplicate of this issue.)
latest/dev/beta/next hard-code the managed port to 49374, which is inside the OS ephemeral range (macOS default 49152–65535). The kernel can hand that port to an unrelated process or outbound connection at any time, so the collisions reported here (symptomsd above, the Tailscale loopback connection in #49009) are not user misconfiguration — they follow from the port choice.
Separately: the supervisor marks a spawned child unhealthy after requestTimeout: 2000 and respawns every spawnDelay: 5000 with no attempt cap. Any start slower than the probe window turns a single bind failure into a permanent spawn storm; we can reproduce the storm with the port completely free.
Two asks:
Pick the managed port outside the ephemeral range (or negotiate a free one).
Use a readiness handshake instead of a fixed 2s window, and cap/back off respawns.
On linux with opencode CLI 2.0.6, each time I start opencode I get ERROR (#1): Error: Timed out waiting for the background service to start.
IMHO it should not start 2 background service processes :
Fixed by #41793 and #50784: the background service now keeps the first startup failure, such as the port-in-use error, and reports it instead of respawning until a generic timeout. This shipped in v2.0.23. If you still get 'Timed out waiting for the background service to start' without the underlying error on that version or later, comment and we'll reopen.
Activity
github-actions commentedon Aug 11, 2026
This issue might be a duplicate of existing issues. Please check:
opencode serveexits/spins silently with no logged errorIf your issue is distinct (e.g. specific to the managed service /
opencode2 service startflow rather thanopencode servedirectly), feel free to clarify and we can keep it open as a separate tracking item.opencode-agent commentedon Aug 12, 2026
Addressed by #41793. Managed service contenders now retain a bounded stderr tail and append it to nonzero-exit/signal startup failures, so port conflicts surface the existing actionable remediation instead of only
Server process exited with code 1. Effect, Promise, and real CLI boundary regressions cover the behavior. Closing as resolved on the v2 branch.nulluserid commentedon Aug 17, 2026
Reproduced a remaining form of this on
0.0.0-beta-17498, after #41793.Port
49374was occupied by an unregistered olderopencode2 serve --serviceprocess. Plainopencode2repeatedly spawned contenders and eventually returned:Running
opencode2 serve --servicedirectly correctly exposed the actionable port-conflict error.The likely remaining gap is contender overlap:
recognizeIncumbentcan take 15 seconds, whileService.ensurekeeps up to two contenders. A finished contender’s captured failure is returned only when no other contender remains. When another contender is still running, that failure is removed and discarded. This can repeat until the overall timeout, hiding the stderr added by #41793.Stopping the old listener immediately restored normal managed startup.
Environment: Fedora Linux 44 x86_64, OpenCode
0.0.0-beta-17498.suse-coder commentedon Aug 26, 2026
This is what i get :
opencdoe2 then does not start. but nothing is using that port: lsof -nP -iTCP:49374 -sTCP:LISTEN shows nothing
benknab commentedon Sep 8, 2026
Still reproducible on
opencode2 v0.0.0-beta-19242on macOS arm64.Running
opencode2repeatedly tried to start the background server, then returned:The log at
~/.local/share/opencode/log/opencode.logand runningopencode2 serve --service --print- logs --log-level debugexposed the underlying error:lsof -nP -iTCP:49374showed nothing, butnetstat -anv -p tcp | rg 49374showed macOS’ssymptomsdlistening on*.49374. A separate socket bind test confirmed “Address already in use.”Switching to a free port restored startup:
opencode2 service set port 49375 opencode2 service startConfirmed the service was listening on
127.0.0.1:49375. The remaining problem is that the CLI stillhides the actionable port-conflict error behind a generic timeout.
sghng commentedon Sep 14, 2026
Reproduced on the release channel,
opencode v2.0.3(macOS 26 / Darwin 27, arm64, bun global install) — so this has shipped to stable, not just next/beta.Root cause confirmed in code (v2 branch):
packages/cli/src/server-process.ts:149— the spawnedserve --servicecorrectly detectsEADDRINUSEand produces the actionable message, including theservice set porthint.packages/client/src/effect/service.ts:122— a finished contender's failure is returned only whencontenders.size === 0. Because the ensure loop keeps one candidate plus one lock probe in flight, each failure arrives while another contender is still pending, so the specific error is dropped every iteration; line 138 then throws the genericTimed out waiting for the background service to startwith nocause. Same pattern inpackages/client/src/promise/service.ts:59.causeto the final timeout error.One extra data point on how the port gets poisoned with no visible listener: in my case
lsof -nP -iTCP:49374 -sTCP:LISTENshowed nothing, and a manual Pythonbind()withSO_REUSEADDRstill failed withEADDRINUSE. The culprit was a stale ESTABLISHED loopback connection,127.0.0.1:49383 -> 127.0.0.1:49374, held by the Tailscale GUI app (notailscale serve/funnelconfig — a coincidental ephemeral-range collision; the hidden peer end was likely a root-owned process, invisible to user-levellsof). On Darwin,SO_REUSEADDRonly permits rebinding when prior sockets are inTIME_WAIT; an active socket with that local port blocksbind()regardless. Quitting Tailscale closed the connection and the managed service started immediately and healthily.So "nothing is listening on the port" does not rule out this failure mode —
lsof -nP -iTCP:<port>without the LISTEN filter (ornetstat -an) is needed, which makes the missing error message even more costly.(Full environment and log excerpts in #49009, closed as a duplicate of this issue.)
jensenojs commentedon Sep 22, 2026
latest/dev/beta/nexthard-code the managed port to 49374, which is inside the OS ephemeral range (macOS default49152–65535). The kernel can hand that port to an unrelated process or outbound connection at any time, so the collisions reported here (symptomsd above, the Tailscale loopback connection in #49009) are not user misconfiguration — they follow from the port choice.Separately: the supervisor marks a spawned child unhealthy after
requestTimeout: 2000and respawns everyspawnDelay: 5000with no attempt cap. Any start slower than the probe window turns a single bind failure into a permanent spawn storm; we can reproduce the storm with the port completely free.Two asks:
bilbonotry commentedon Sep 24, 2026
On linux with opencode CLI 2.0.6, each time I start opencode I get ERROR (#1): Error: Timed out waiting for the background service to start.

IMHO it should not start 2 background service processes :
neriousy commentedon Oct 20, 2026
Fixed by #41793 and #50784: the background service now keeps the first startup failure, such as the port-in-use error, and reports it instead of respawning until a generic timeout. This shipped in v2.0.23. If you still get 'Timed out waiting for the background service to start' without the underlying error on that version or later, comment and we'll reopen.