feat(node): Auto-register Koa error handler on app start - #23463
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e8b1047. Configure here.
size-limit report 📦
|
| timestamp: expect.any(Number), | ||
| trace_id: expect.stringMatching(/[a-f0-9]{32}/), | ||
| }, | ||
| { |
There was a problem hiding this comment.
we do not add a middleware ourselves anymore, so this disappears here.
JPeer264
left a comment
There was a problem hiding this comment.
q: Any reason why we don't remove it already?
my main reasoning was that it is impossible to prepare this in v10, and it likely pretty high-impact (e.g. everyone using koa has this). and the cost of keeping this around in v11 is rather small. |
The Koa error handler now registers itself automatically when the app starts, so
`setupKoaErrorHandler` no longer needs to be called. The handler is attached as an
order-independent `app.on('error')` listener via a new orchestrion `callback`
channel; the listener is added after koa registers its own default error listener
so koa's built-in error logging is preserved.
`setupKoaErrorHandler` and the shared `attachKoaErrorHandler` are both deprecated;
`setupKoaErrorHandler` remains an idempotent delegate for backwards compatibility.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
revert hasspansenabled
fix koa test
fix span attachment to error
77b29b8 to
40cae03
Compare

The Koa error handler is now registered automatically when the app starts, so
setupKoaErrorHandlerno longer needs to be called. This mirrors the Hapi change and removes the last manual setup step for Koa error capture.How it works
Koa's
Applicationis anEventEmitterand emits'error'for every request error that bubbles up unhandled — the same set of errors a top-level try/catch middleware would see, but order-independent. So instead of injecting atry/catchmiddleware (whose position in the onion stack was load-bearing), we attach a singleapp.on('error')listener.Auto-registration rides a new orchestrion channel on
Application.prototype.callback.app.listen()always funnels throughcallback(), so this also covershttp.createServer(app.callback()).Decisions
end, notstart. Koa registers its own defaulterrorlistener insidecallback()— but only if none exist yet (if (!this.listenerCount('error')) this.on('error', this.onerror)). Attaching before that runs would suppress koa's built-in error logging. Acting onend(after the method body) means koa's default listener is already in place and ours is added alongside it.app.on('error')over a first-positiontry/catchmiddleware. Event listeners are additive and order-independent, so there is no ordering conflict with a user's own error handling: if a user middleware catches and handles an error, koa never emits and we correctly don't capture; if it's unhandled, our listener and any userapp.on('error')both run.setupKoaErrorHandlerstays as an idempotent delegate (deprecated) rather than a hard no-op, so a direct call still works without orchestrion (e.g. error capture with tracing disabled). An idempotency marker on the app means auto-registration plus a manual call never stack up duplicate listeners.attachKoaErrorHandleris also deprecated and marked internal — it exists only so the deprecatedsetupKoaErrorHandlercan delegate to it, and should not be called directly.koa/folder to match the Hapi layout.Auto-registration is exercised end-to-end by dropping the manual call from the koa integration-test scenario and the e2e app; a new unit suite covers the attach behaviour (single idempotent listener, guards, and capture mechanism).
A follow-up will do the same for Express.