Attach an error listener to the emitter you own before starting work that may emit errors. EventEmitter gives the error event special behavior; a global process exception handler is not a substitute for defining recovery at the component boundary.
Reproduce the boundary in a disposable fixture
Handle failures at the emitter lifecycle instead of relying on a global catch-all.
Use a new empty temporary directory for this fixture. The example creates only local test data. Commands marked with example.invalid do not identify a real service.
const assert = require('node:assert/strict');
const {EventEmitter} = require('node:events');
const noHandler = new EventEmitter();
assert.throws(() => noHandler.emit('error',new Error('fixture')),/fixture/);
const owned = new EventEmitter();
let observed;
owned.on('error', err => { observed=err.message; });
owned.emit('error',new Error('handled'));
assert.equal(observed,'handled');
console.log('owned error observed');Observed result
owned error observedWhat the result means
The unhandled error emission throws synchronously in this small fixture, so the assertion can observe it. The owned emitter has a listener in place and delivers the error to that listener. Real I/O often emits later, after the caller original try block has ended. Wrapping only the component construction or start call in try/catch does not establish a handler for a later event.
Choose the correction for your workflow
At the place where your application creates or receives a component, read its error and close contract, attach handlers and then start it. Decide whether an error rejects the current operation, closes the component, retries under a bound or stops the service. If the emitter is hidden inside a library, use its documented promise, callback or error hook rather than monkey-patching every emitter. Record enough context to locate the failed operation while keeping credentials and payloads out of logs. Handle teardown as well as the initial failure so a component is not left half-active.
Limits and the next check
The fixture proves emitter-level delivery, not a safe general recovery policy. An async listener can reject independently; do not assume a normal error listener makes every returned promise observed. Node errorMonitor observes error events without consuming the special failure behavior. Raising max listeners does not repair missing error ownership or remove a listener leak. Process-level failure reporting can be valuable, but continuing normal work after an uncaught exception needs a separately designed safety policy.
Related: Compare the related workflow boundary.
This isolated example was executed on macOS on November 10, 2026 (KST). Available tools: node v26.5.0, git git version 2.39.3 (Apple Git-145), npm 11.17.0, jq jq-1.7.1-apple. Shell fixtures use Bash and repository-path identity uses Python 3. This checks the illustrated contract, not your project, host service or every tool version.