Skip to content

fix(nextjs): Make request data available to tracesSampler for edge middleware root spans#22232

Open
s1gr1d wants to merge 1 commit into
developfrom
sig/nextjs-edge-middleware
Open

fix(nextjs): Make request data available to tracesSampler for edge middleware root spans#22232
s1gr1d wants to merge 1 commit into
developfrom
sig/nextjs-edge-middleware

Conversation

@s1gr1d

@s1gr1d s1gr1d commented Jul 13, 2026

Copy link
Copy Markdown
Member

On the edge runtime, Next.js's OTel instrumentation creates and samples the Middleware.execute root span before the Sentry middleware wrapper runs. So normalizedRequest was never on the isolation scope at sampling time, and tracesSampler received undefined.

This adds a beforeSampling hook in the edge SDK which populates normalizedRequest (method, URL, query string) based on HTTP span attributes. It also extends the edge spanStart handler to fork the isolation scope for Middleware.execute root spans (similar to what #22013 did on the Node side after vercel/next.js#95357 made middleware a detached root span).

The isolation-scope fork is extracted into a shared maybeForkIsolationScopeForRootSpan utility used by both the Node and edge handlers.

Fixes #22200

@s1gr1d s1gr1d requested a review from a team as a code owner July 13, 2026 15:42
@s1gr1d s1gr1d requested review from chargome, mydea and nicohrubec and removed request for a team July 13, 2026 15:42
Comment on lines +110 to +112
if (isolationScope.getScopeData().sdkProcessingMetadata?.normalizedRequest) {
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: In warm serverless environments, stale normalizedRequest data from a previous request can be reused because the global default isolation scope is not reset between requests.
Severity: MEDIUM

Suggested Fix

The global default isolation scope should be cleared or reset at the beginning of each request in serverless environments. This ensures that buildContextWithSentryScopes starts with a clean scope and does not reuse stale data from previous invocations in the same warm worker.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/nextjs/src/edge/index.ts#L110-L112

Potential issue: In warm serverless environments like Vercel Edge or Cloudflare Workers,
the module-level singleton from `getDefaultIsolationScope()` is not reset between
requests. This causes stale `normalizedRequest` data from a previous request to persist.
When a subsequent request is processed, the `beforeSampling` hook incorrectly finds
existing `normalizedRequest` data and exits early. As a result, the sampler uses the
stale data from the first request to make a sampling decision for the second request,
potentially leading to incorrect sampling.

Did we get this right? 👍 / 👎 to inform future reviews.

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.

Next.js middleware: normalizedRequest never reaches tracesSampler on the edge runtime, so #21833 has no effect there

1 participant