Repository navigation
Open
Labels
Description
Summary
opencode serve accumulates orphaned /usr/bin/bash -l processes when PTY
sessions are created but POST /api/pty/{id}/connect-token is denied (403).
In one observed window, 1037 sessions were created in 49 minutes, connect
failed every time, and 846 processes (~1.6 GB PSS, 846 pty devices) were still
running 8+ hours later until the service was restarted. Nothing reaps
never-connected sessions.
Environment
- opencode version: v2.0.10
- OS: Linux 6.19.14-edge-sm8250 aarch64 (Xiaomi elish)
- Terminal: headless
opencode serve --service(no TUI attached); TERM=xterm-256color, TERM_PROGRAM unset - Shell: /usr/bin/bash
- Install/channel: latest release (official installer,
~/.opencode/bin/opencode) - Active plugins: none found (
opencode.jsonhas nopluginsentry; no local plugin dirs)
Reproduction
- Start
opencode serve --service(listens on0.0.0.0:4096). - From another host,
POST /api/pty→ succeeds; server logs
message="creating session" id=pty_... cmd=/usr/bin/bash args=["-l"]
and spawns the process. POST /api/pty/{id}/connect-token→403(also observed404on
subsequentPUT /api/pty/{id}).- The client never attaches and repeats steps 2–3
(observed 1037 creates between 2026-09-22T09:17:25Z and 10:06:16Z,
peak 177 connect-token 403s in one minute). psshows the count of/usr/bin/bash -lchildren of the serve process
growing monotonically; after the client stops, they persist indefinitely.
Expected Behavior
A session whose connect-token is denied, or that is never attached, should be
torn down promptly and its process reaped. Concurrent/unattached PTY sessions
should be bounded (max sessions / TTL), so a misbehaving client cannot grow
resource usage without limit.
Actual Behavior
message="creating session": 1037 exact matches, allcmd=/usr/bin/bash args=["-l"](1035 within the 49-minute window; 2 earlier on 2026-09-19).- Every logged
connect-tokenresponse was an error:
403× 1033,404× 23, no 2xx observed. - 846 orphan
bash -lprocesses still alive 8+ hours after creation, each
holding its own pty (/dev/pts846 of 847 slots), combined PSS ≈ 1648 MB
(naive RSS sum 4.2 GB including shared pages). - The processes only disappeared when the service restarted (pty master close
→ SIGHUP). Note interactive bash ignores SIGTERM, so cleanup needs
SIGHUP/SIGKILL.
Additional Context
- Log evidence for one session (create succeeded, connect denied ~1s later):
timestamp=2026-09-22T09:17:25.563Z message="creating session" id=pty_0c867... cmd=/usr/bin/bash args=["-l"] cwd=<redacted> http.span=17 role=server
timestamp=2026-09-22T09:17:26.596Z message="Sent HTTP response" http.method=POST http.url=/api/pty/pty_0c867.../connect-token http.status=403 role=server
- Client was another host on the same LAN (app unidentified); it re-created
sessions instead of reusing them (PUT /api/pty/{id}also returned404,
82×404 total in window). - Auth question for maintainers: create produced its full side effect
(session + spawned process) while every connect-token attempt was denied 403.
Since serve binds0.0.0.0:4096, please verifyPOST /api/ptyis auth-gated
the same way as connect-token — if create is reachable without credentials,
any host can spawn processes; at the observed growth rate a sustained client
would exhaust/dev/ptswithin a day. - 191 of the 1037 sessions disappeared before restart (mechanism unknown);
the remaining 846 persisted until restart. - Related (same class, different subsystem): mcp: orphaned local MCP server processes accumulate after sessions end #50363, serve (1.18.25): MCP child processes accumulate on web-client reconnects until the server OOMs #46035.
- Workaround: restart the service. No plugins or recent config changes.
- Frequency: reproduced twice (2 sessions on Sep 19, 1035 on Sep 22), whenever
the client entered its retry loop.
Activity
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I could reproduce this on v2.0.10, and it still happens on the latest
dev(fa1260d).Steps:
opencode serve --hostname 0.0.0.0with no TUI attached.POST /api/ptycalls. After each one, callPOST /api/pty/{id}/connect-tokenwith a cross-originOriginheader, as a web app on another LAN host would send.Result:
403every time.bash -lprocesses were running, andGET /api/ptylisted all 50 sessions.On your auth question:
POST /api/ptydoes require the server password (unauthenticated requests get401), so other hosts can't spawn shells without credentials. The403comes from the origin check on connect-token, whichcreatedoesn't have. Your client must have had the password but been rejected for its origin.The script below reproduces it. Related, but about MCP processes rather than PTYs:
Reproduction script (repro.sh)
Run it:
bash repro.sh