HarperFast / HarperFast/harper
DeployLifecycle exceeds Node's default max listeners on a normal boot, logging a spurious memory-leak warning
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Summary
`DeployLifecycle` extends `EventEmitter` without raising the listener cap, but one `deploy:start` listener is registered per live component scope. A normal instance therefore crosses Node's default limit of 10 during startup and logs:
```
(node:1) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 deploy:start
listeners added to [DeployLifecycle]. MaxListeners is 10. Use emitter.setMaxListeners() to increase limit
```
This appears to be a false positive rather than a leak: the listeners are added and removed in matched pairs, so the count reflects how many component scopes are concurrently loaded, not unbounded growth.
## Where
On `origin/main`:
- `components/deployLifecycle.ts:51` — `class DeployLifecycle extends EventEmitter<...>`, no `setMaxListeners()`
- `components/Scope.ts` — registers `deployLifecycle.on('deploy:start', ...)` per scope and removes it with the matching `.off(...)` on teardown
- `components/componentLoader.ts` — same add/remove pairing for its own handler
## Why it is worth fixing anyway
The warning says "Possible EventEmitter memory leak detected" on a healthy boot, so it trains operators to ignore a message that would be meaningful if the count ever *did* start climbing across repeated `deploy_component` calls. It also fires on any instance with more than ~10 components, which is not an unusual shape.
## Suggested fix
Call `setMaxListeners()` on the `DeployLifecycle` instance with a bound that reflects "one per component scope" (or `0`/`Infinity` if the pairing is considered authoritative). If the intent is instead that only a small fixed number of listeners should ever exist, then the per-scope registration is the thing to revisit — but the `.on`/`.off` pairing suggests per-scope is deliberate.
Low priority: log noise, no observed functional impact.
Contributor guide
Research direction
Start in components/deployLifecycle.ts:51, then trace the matching listener registration and teardown in components/Scope.ts and components/componentLoader.ts. Reproduce a normal boot to confirm the warning, establish an appropriate listener bound from the per-scope behavior, and verify that repeated deploy_component calls do not produce spurious warnings or unbounded listener growth.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, typescript
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100