[BUG] ProcessTransport adds global process.on('exit') listener per query() call, causing MaxListenersExceeded warning
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Each call to query() from the Claude Agent SDK creates a new ProcessTransport instance. Each ProcessTransport registers a global process.on("exit", handler) listener (to kill the spawned Claude process if the Node.js host exits).
While each listener IS properly cleaned up when the child process exits (process.off("exit", handler)), if there are 11+ concurrent or overlapping queries before any child process exits, the global listener count exceeds Node's default MaxListeners limit of 10, triggering:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
11 exit listeners added to [process]. MaxListeners is 10.
Use emitter.setMaxListeners() to increase limit
This happens in extensions and applications that use the SDK to manage multiple concurrent sessions (e.g., VS Code extensions with multiple chat tabs, or applications spawning parallel agent queries).
The relevant code path in the compiled SDK bundle (ProcessTransport / hF class):
// In constructor/initialize:
process.on("exit", this.processExitHandler)
// Cleanup when child exits:
child.once("exit", () => {
process.off("exit", this.processExitHandler);
});
What Should Happen?
The SDK should either:
- Call
process.setMaxListeners()to increase the limit proportionally when adding exit handlers, or - Use a single shared exit handler that tracks all active processes instead of one listener per ProcessTransport instance, or
- Document the behavior so consumers know to call
process.setMaxListeners()themselves.
Option 2 would be the cleanest fix — a single module-level handler managing a Set<ChildProcess> would eliminate the per-instance listener entirely.
Error Messages/Logs
[Extension Host] (node:51900) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 exit listeners added to [process]. MaxListeners is 10. Use emitter.setMaxListeners() to increase limit
Steps to Reproduce
- Use the Claude Agent SDK (
@anthropic-ai/claude-agent-sdk) in a VS Code extension or Node.js application - Call
query()11+ times concurrently (e.g., multiple chat sessions, parallel agent queries) - Observe the MaxListenersExceededWarning in the extension host console
This is reproducible with any application that maintains multiple concurrent SDK sessions. Each query() call spawns a process and registers a global process.on("exit") listener.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.92 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
VS Code integrated terminal
Additional Information
SDK version: @anthropic-ai/claude-agent-sdk ^0.2.0
Environment: VS Code Extension Host (Node.js), Windows 11
Claude Code version: Latest
Workaround: Consumers can suppress the warning by calling process.setMaxListeners(20) early in their activation, but this shouldn't be necessary — the SDK should manage its own listener count.
Note: This is NOT a memory leak — the listeners are properly cleaned up when processes exit. It's purely a peak-concurrency issue where the number of active ProcessTransport instances temporarily exceeds the default MaxListeners threshold.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗