Skip to content

fix(web): silence MaxListenersExceededWarning on proxied rewrites - #1697

Merged
brendan-kellam merged 2 commits into
mainfrom
brendan/fix-max-listeners-warning
Sep 30, 2026
Merged

brendan-kellam merged 2 commits into
mainfrom
brendan/fix-max-listeners-warning

Conversation

@brendan-kellam

@brendan-kellam brendan-kellam commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The web server logs this on every request that goes through an external rewrite (/ingest/* → PostHog, /monitoring → Sentry tunnel):

(node:172) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added to [ServerResponse]. MaxListeners is 10. Use emitter.setMaxListeners() to increase limit

In prod this is ~100–200k log lines/day; staging shows the same pattern.

It's a false positive. Since Next 16.3 (which we adopted in #1594), the external rewrite proxy attaches 9 close listeners to each ServerResponse, from router-utils/proxy-request.js, its bundled httpxy and the compression stream cleanup. Sentry adds 2 more, from server-subscription.js (isolation scope) and record-request-session.js. That's 11, one over Node's default limit. All of them belong to the one response and are released with it, so nothing accumulates.

Upstream issue: vercel/next.js#97757 (open; the fix PR vercel/next.js#97824 was closed unmerged).

Fix

In instrumentation.ts, subscribe to Node's http.server.request.start diagnostics channel and call response.setMaxListeners(20). The channel fires before Next handles the request, so the limit is in place before any listener is attached. It's scoped to server responses rather than raising EventEmitter.defaultMaxListeners, so the warning stays meaningful for every other emitter. The comment links the upstream issue so this can be removed once Next trims its listeners.

Testing

  • Reproduced locally with a minimal Next 16.3.3 app with one external rewrite: without Sentry, 9 listeners and no warning; with Sentry.init (no tracing, matching staging and prod), 11 listeners and one warning per proxied request.
  • With this change applied to that repro, warnings went from 3 → 0 over 3 proxied requests while the same 11 listeners were still attached.
  • On staging, bursts to /ingest/* and /monitoring each produced warnings; /api/health, the polling APIs, /metrics and pages produced none.

🤖 Generated with Claude Code


Note

Low Risk
Startup-only instrumentation that raises per-response listener limits; no auth, data, or request-handling logic changes.

Overview
Stops false-positive MaxListenersExceededWarning spam on proxied external rewrites (PostHog /ingest/*, Sentry /monitoring), which was flooding production logs (~100–200k lines/day) after Next 16.3’s rewrite proxy plus Sentry attach 11 close listeners per ServerResponse.

In instrumentation.ts, on the Node runtime it subscribes to http.server.request.start and calls response.setMaxListeners(20) before Next/Sentry attach listeners—scoped per response instead of raising the global default. The changelog Unreleased section documents the fix.

Reviewed by Cursor Bugbot for commit 3a614f7. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes
    • Silenced a false-positive MaxListenersExceededWarning that appeared on requests proxied through external rewrites.

brendan-kellam and others added 2 commits September 29, 2026 18:38
Next 16.3's external rewrite proxy attaches 9 `close` listeners to each
ServerResponse, and Sentry adds 2 more, crossing Node's default limit of
10 on every `/ingest/*` and `/monitoring` request. The listeners are
released with the response, so this is a false positive that produces
~100-200k log lines/day in prod.

Raise the limit to 20 on server responses only, via the
`http.server.request.start` diagnostics channel, so the warning stays
meaningful for every other emitter.

See vercel/next.js#97757

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: f0b707c6-5065-46a6-b9ec-3b5873e2a9d1

📥 Commits

Reviewing files that changed from the base of the PR and between 727191b and 3a614f7.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • packages/web/src/instrumentation.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.


Walkthrough

On Node.js, instrumentation sets the maximum listener limit to 20 for responses included in HTTP request-start events. The Unreleased changelog records that the false-positive warning was silenced.

Changes

Response listener limit

Layer / File(s) Summary
Set response listener limit
packages/web/src/instrumentation.ts, CHANGELOG.md
Node.js instrumentation listens for HTTP request-start events and sets the maximum listener limit to 20 when a response is present. The changelog records the warning fix.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: msukkari

Merge Risk: ⚪ Minimal · up to 3a614

The response-specific limit is applied before the affected listener burst, and no other material issue is established. The change appears ready to merge.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: silencing the MaxListenersExceededWarning for proxied rewrites.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 390e8b2 into main Sep 30, 2026
12 checks passed
@brendan-kellam
brendan-kellam deleted the brendan/fix-max-listeners-warning branch September 30, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant