Skip to content

fix(nextjs): Drop the request span that only runs the proxy - #25386

Draft
Lms24 wants to merge 5 commits into
developfrom
lms/fix-nextjs-proxy-handle-request-segment
Draft

Lms24 wants to merge 5 commits into
developfrom
lms/fix-nextjs-proxy-handle-request-segment

Conversation

@Lms24

@Lms24 Lms24 commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Behind a proxy, Next.js runs each request through two handleRequest calls: one only runs the proxy, the other renders the route. Since Next.js 16.3 the proxy span is no longer a child of the first call's span, so that span became an empty GET segment with op http.server, counted next to the real one. We now drop it at span start with ignoreSpans. At start, its name and attributes are the same as the real span's, so the only signal is the middlewareInvoke flag Next.js sets on the request.

For this, core gets a beforeSpanStart hook that runs right before ignoreSpans is checked and can change the span's name and attributes. Next.js uses it to mark the proxy-only span, and the existing sentry.drop_transaction ignore pattern drops it. To read the flag, the Next.js SDK keeps the request of each isolation scope, from the httpServerRequest hook of the Node.js SDK.

Fixes #25370

🤖 Generated with Claude Code

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread dev-packages/e2e-tests/test-applications/nextjs-16/tests/middleware.test.ts Outdated
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 29.88 kB - -
@sentry/browser - with treeshaking flags 28.02 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.92 kB - -
@sentry/browser (incl. Tracing) 52.1 kB +0.07% +35 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 52.11 kB +0.07% +33 B 🔺
@sentry/browser (incl. Tracing, Profiling) 55.05 kB +0.06% +33 B 🔺
@sentry/browser (incl. Tracing, Replay) 91.85 kB +0.04% +35 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 80.72 kB +0.05% +35 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 96.58 kB +0.04% +37 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 109.53 kB +0.04% +38 B 🔺
@sentry/browser (incl. Feedback) 47.4 kB - -
@sentry/browser (incl. sendFeedback) 34.94 kB - -
@sentry/browser (incl. FeedbackAsync) 40.05 kB - -
@sentry/browser (incl. Metrics) 30.9 kB - -
@sentry/browser (incl. Logs) 31.18 kB - -
@sentry/browser (incl. Metrics & Logs) 31.81 kB - -
@sentry/react 31.7 kB - -
@sentry/react (incl. Tracing) 54.42 kB +0.07% +33 B 🔺
@sentry/vue 38.07 kB +0.09% +33 B 🔺
@sentry/vue (incl. Tracing) 55.04 kB +0.07% +37 B 🔺
@sentry/svelte 29.9 kB - -
@sentry/remix (Remix 3 client bundle) 57.12 kB +0.07% +35 B 🔺
CDN Bundle 31.64 kB - -
CDN Bundle (incl. Tracing) 52.62 kB +0.08% +38 B 🔺
CDN Bundle (incl. Logs, Metrics) 33.84 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 54.56 kB +0.07% +35 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 74.77 kB - -
CDN Bundle (incl. Tracing, Replay) 90.29 kB +0.05% +39 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 92.22 kB +0.05% +40 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 96.44 kB +0.04% +38 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 98.39 kB +0.05% +41 B 🔺
CDN Bundle - uncompressed 93.18 kB - -
CDN Bundle (incl. Tracing) - uncompressed 156.15 kB +0.08% +114 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.72 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 162.1 kB +0.08% +114 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 229.76 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 276.31 kB +0.05% +114 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 282.26 kB +0.05% +114 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 290.02 kB +0.04% +114 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 295.95 kB +0.04% +114 B 🔺
@sentry/nextjs (client) 56.83 kB +0.06% +33 B 🔺
@sentry/sveltekit (client) 52.48 kB +0.07% +34 B 🔺
@sentry/core/server 41.16 kB +0.09% +33 B 🔺
@sentry/core/browser 13.85 kB +0.27% +36 B 🔺
@sentry/node 152.89 kB +0.04% +48 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 83.84 kB - -
@sentry/node - without tracing 94.67 kB +0.05% +40 B 🔺
@sentry/node - without channel injection 131.11 kB +0.03% +34 B 🔺
@sentry/aws-serverless 102.83 kB +0.04% +38 B 🔺
@sentry/cloudflare (withSentry) - minified 210.71 kB +0.06% +114 B 🔺
@sentry/cloudflare (withSentry) 522.78 kB +0.05% +247 B 🔺
@sentry/nextjs/cloudflare (withSentry) - minified 229.27 kB +0.44% +995 B 🔺

View base workflow run

Lms24 and others added 3 commits October 16, 2026 17:27
…roxy

Requests behind the proxy produce an extra route-less `GET` segment with
op `http.server` next to the route segment. This test shows it for an API
route and a page.

Refs #25370
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Since Next.js 16.3 the proxy span is no longer a child of the
`BaseServer.handleRequest` span that runs it, so that span became an empty
`http.server` segment next to the one of the route. Drop it at span start
in `beforeSampling`, based on the `middlewareInvoke` flag Next.js sets on
the request. Its attributes at start are the same as the route's.

For this, core now keeps the incoming request on the request's isolation
scope and enforces the `beforeSampling` decision again, which it had
stopped doing when `SentrySampler` was removed.

Fixes #25370
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Instead of enforcing the `beforeSampling` decision in core, add a
`beforeSpanStart` hook that runs right before `ignoreSpans` is checked and
can change the name and attributes of a span. The Next.js SDK uses it to mark
the request span that only runs the proxy with `sentry.drop_transaction`,
which the existing Next.js `ignoreSpans` pattern drops.

Refs #25370
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Lms24
Lms24 force-pushed the lms/fix-nextjs-proxy-handle-request-segment branch from a49a615 to 0453bca Compare October 16, 2026 15:27

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0453bca. Configure here.

Comment thread packages/nextjs/src/server/serverSpanHooks.ts Outdated
Lms24 and others added 2 commits October 16, 2026 18:06
…gment

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Instead of keeping the incoming request on a hidden field of the isolation
scope in core, the Next.js SDK keeps it in its own map, filled from the
`httpServerRequest` hook that the Node.js SDK emits for every incoming request.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Lms24
Lms24 force-pushed the lms/fix-nextjs-proxy-handle-request-segment branch from 8c57d77 to 1a8666d Compare October 16, 2026 16:06

This branch has not been deployed

No deployments
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.

nextjs: Next 16 request yields a route-less http.server segment named only by method, plus the route-named one

1 participant