Repository navigation
Description
Environment
- opencode version: 1.15.10
- Mode:
opencode serve --hostname 0.0.0.0 --port 4096(headless / server mode) - Platform: Linux x86_64 (Fedora 43, kernel 6.19.6-200.fc43)
- Runtime: Bun compiled binary (
~/.opencode/bin/opencode, 144 MB ELF)
Summary
When running opencode serve, a MaxListenersExceededWarning fires within ~30 seconds of each server start (i.e. after enough client sessions connect). The emitter accumulates listeners indefinitely; memory grows unboundedly across sessions and can reach several GB before the process is killed by OOM or the OS.
Warning output (from journald)
MaxListenersExceededWarning: Possible EventTarget memory leak detected.
11 event listeners added to [QL]. MaxListeners is undefined.
Use events.setMaxListeners() to increase limit
emitter: QL {
_events: [Object ...],
_eventsCount: 1,
_maxListeners: undefined,
[Symbol(kCapture)]: false,
emit: [Function: emit],
...
},
type: "event",
count: 11,
at overflowWarning (node:events:185:19)
at addListener (node:events:158:22)
at ~effect/Effect/evaluate (/$bunfs/root/chunk-1h0fh6v6.js:25:4492)
at runLoop (/$bunfs/root/chunk-1h0fh6v6.js:25:2045)
at evaluate (/$bunfs/root/chunk-1h0fh6v6.js:25:1435)
at runTasks (/$bunfs/root/chunk-1h0fh6v6.js:11:33531)
at afterScheduled (/$bunfs/root/chunk-1h0fh6v6.js:11:33418)
Observed memory pattern (from systemd accounting over ~12 h)
| Invocation | CPU time | Memory peak |
|---|---|---|
| 1 | 2 m 52 s | 1.1 GB |
| 2 | 2 m 19 s | 9.6 GB |
| 3 | 22 m 23 s | 2.1 GB |
| 4 | 26 s | 683 MB |
| 5 | 53 m 55 s | 4.3 GB |
| Final (before manual stop) | 37 m 57 s | 1.5 GB |
Memory peaks are non-monotone (restart clears heap) but always balloon well above baseline within minutes. The 9.6 GB spike suggests the leak compounds quickly under concurrent or long-lived sessions.
Root cause hypothesis
The stack points to Effect-ts's internal scheduler (runTasks / afterScheduled / evaluate). Each call to ~effect/Effect/evaluate registers a new "event" listener on an internal QL EventEmitter but does not remove it after the fiber/task completes. In server mode, each client session or SSE subscription forks new fibers, so listeners accumulate proportionally to session count.
QL is a minified class name in the compiled bundle (chunk-1h0fh6v6.js); in source it is likely Queue or a similar bounded-queue abstraction from effect/Queue or effect/Runtime.
Steps to reproduce
opencode serve --hostname 0.0.0.0 --port 4096- Open ≥ 10 client sessions (or reconnect repeatedly from
opencode attach) - Observe
MaxListenersExceededWarningin stderr within ~30 s - Leave server running for several hours — memory grows into the GB range
Impact
- Server process OOM-killed or must be manually restarted
- Breaks unattended / always-on headless deployments (the primary use case for
opencode serve)
Suggested fix
Find every .on("event", ...)" / .addListener("event", ...)call on the relevant Effect-ts emitter in the server session/subscription path and pair it with a corresponding.off()or.removeListener()` in the cleanup/finalizer. Alternatively, scope the emitter per session rather than sharing a singleton.
Activity
github-actions commentedon May 25, 2026
This issue might be a duplicate of existing issues. Please check:
MaxListenersExceededWarningfrom the same Effect-ts internal emitter (QL/iz) with the same stack trace (~effect/Effect/evaluate→runLoop→runTasks→afterScheduled) when starting the web interface/server mode.opencode servemode, same massive memory leak with unbounded virtual memory growth — reported just hours earlier.d9394 commentedon Jun 30, 2026
opencode server listening on http://127.0.0.1:4096
MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 event listeners added to [MZ]. MaxListeners is undefined. Use events.setMaxListeners() to increase limit
emitter: MZ {
_events: [Object ...],
_eventsCount: 1,
_maxListeners: undefined,
[Symbol(kCapture)]: false,
emit: [Function: emit],
setMaxListeners: [Function: setMaxListeners],
getMaxListeners: [Function: getMaxListeners],
addListener: [Function: addListener],
on: [Function: addListener],
prependListener: [Function: prependListener],
once: [Function: once],
prependOnceListener: [Function: prependOnceListener],
removeListener: [Function: removeListener],
off: [Function: removeListener],
removeAllListeners: [Function: removeAllListeners],
listeners: [Function: listeners],
rawListeners: [Function: rawListeners],
listenerCount: [Function: listenerCount],
eventNames: [Function: eventNames],
},
type: "event",
count: 11,
I get the same problem on my cli-server with v1.17.11
MarthinL commentedon Jul 15, 2026
FWIW, I keep getting the same error, but I don't have multiple clients as suggested triggers the issue by the steps to reproduce statement. What I have noticed though, is that there is some kind of automatic refresh happening on the web ui (which I notice because it sometimes messes with the scroll position on update). It could be that the memory leak / connections not cleaned up is triggered by some imperfect event handling that re-initialise connections without cleaning out the old one, likely because it (mistakenly) things the old connection is already lost or never existed or some bad assumption like that. Just going to leave the comment here in case it is useful to someone. It is frustrating to see how many times this had been reported and how long it has existed without getting resolved.
github-actions commentedon Sep 14, 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.