-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Is there an existing issue for this?
- I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- I have reviewed the documentation https://docs.sentry.io/
- I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Sentry Saas (sentry.io)
Which SDK are you using?
@sentry/node
SDK Version
10.34.0
Framework Version
No response
Link to Sentry event
No response
Reproduction Example/SDK Setup
Traces showing suppression (outgoing HTTP spans become Noop):
/api/routes/upsert: https://pedestalai.sentry.io/performance/trace/e80b852a94c759037126461bc6cd7e46//api/routes/stops: https://pedestalai.sentry.io/performance/trace/dcdbd3b9ea76f4d35eb164d08a415a7d//api/calls/initiate: https://pedestalai.sentry.io/performance/trace/c003b8d1aea8d8aef9258b2facb9fbf6//api/texts/initiate: https://pedestalai.sentry.io/performance/trace/de751ee5774e841fe179e090a3d6fa6b//api/notifications/delay: https://pedestalai.sentry.io/performance/trace/7e9560ee7f0aa3a83723bc6df670c77c/
Clean traces (no suppression, for comparison):
/api/cron/data-cleanup: https://pedestalai.sentry.io/performance/trace/046b2ad2cafe310a180259adc5d6222e//api/health: https://pedestalai.sentry.io/performance/trace/5598ab056bc3032c2ae5ee296f96345d/
Steps to Reproduce
- Deploy a Next.js app to Vercel serverless with
@sentry/nextjsandtracesSampleRate: 1.0 - Create API routes that make outgoing HTTP requests (e.g.,
fetch()to external APIs, Twilio SDK calls) - Enable debug logging:
debug: truein Sentry config - Send traffic to the API routes
- Observe debug logs showing
Instrumentation suppressed, returning Noop Spanfor outgoing HTTP requests
Expected Result
All outgoing HTTP requests within a traced route handler should produce child spans, e.g.:
fetch()calls to external APIs- Twilio SDK HTTP requests
- Any other instrumented HTTP client calls
Timing pattern observed:
1767803936358 | ✅ Starting sampled root span - POST /api/routes/upsert
1767803936360 | ✅ Starting span - executing api route
1767803936384 | ✅ prisma:client:operation starts
... | ✅ (many successful Prisma DB operations)
1767803936460 | ✅ Last Prisma operation completes
1767803936461 | ❌ Instrumentation suppressed, returning Noop Span
1767803936461 | ❌ [Tracing] Not injecting trace data for url
1767803936463 | ❌ Instrumentation suppressed (x2 more)
1767803936465 | ✅ Finishing span "executing api route"
1767803936466 | ✅ Finishing root span
The suppression consistently happens:
- AFTER all database/business logic completes
- BEFORE the response is sent
- Sometimes AFTER the root span finishes (likely during Sentry telemetry flush)
Actual Result
Outgoing HTTP requests are silently suppressed with:
Sentry Logger [log]: Instrumentation suppressed, returning Noop Span
Sentry Logger [log]: [Tracing] Not injecting trace data for url because tracing is suppressed.
Pattern:
- ✅ Root span starts successfully
- ✅ Child spans for route execution work fine
- ❌ Outgoing HTTP requests (fetch calls) are suppressed → Noop spans
- ✅ Root span finishes successfully
Scale of impact:
| Route | Traces Analyzed | Avg Suppressions/Request |
|---|---|---|
/api/routes/upsert |
224 | ~6.5 |
/api/routes/stops |
140 | ~6.6 |
/api/notifications/delay |
27 | ~7.3 |
/api/texts/initiate |
16 | ~6.4 |
/api/metrics |
12 | ~6.7 |
/api/calls/initiate |
8 | ~6.3 |
Some routes are completely clean (0 suppressions): /api/health, /api/cron/data-cleanup, /api/cron/eta-notifications.
Additional Context
Root Cause Analysis
After investigating the SDK source, we believe the issue is caused by suppressTracing() context leaking in serverless environments.
How suppressTracing() works:
typescript
// packages/opentelemetry/src/utils/suppressTracing.ts
export function suppressTracing<T>(callback: () => T): T {
const ctx = suppressTracingImpl(context.active());
return context.with(ctx, callback);
}
This is used by the SDK transport to prevent creating spans for Sentry's own HTTP requests (avoiding infinite recursion). However, in Vercel serverless, this suppression context appears to leak into subsequent async operations.
Evidence from logs:
Sentry Logger [log]: Flushing events...
Sentry Logger [log]: SpanExporter exported 0 spans, 1 spans are waiting for their parent spans to finish
Sentry Logger [log]: Flushing outcomes...
Sentry Logger [log]: No outcomes to send
Sentry Logger [log]: Instrumentation suppressed, returning Noop Span <-- Leak!
Sentry Logger [log]: [Tracing] Not injecting trace data for url because tracing is suppressed.
Hypotheses (ranked by likelihood):
- AsyncLocalStorage / async context propagation timing issue (HIGH): suppression context propagated to concurrent/subsequent ops when transport flushes
- Shared context in edge/serverless environments (MEDIUM): Vercel's runtime may not fully isolate async contexts (SDK already has
IsolatedPromiseBufferfor edge, suggesting awareness of this) - Promise chain context loss (MEDIUM): transport uses
suppressTracing(() => fetch(...).then(...))which may not restore context cleanly
Relevant code locations:
packages/opentelemetry/src/utils/suppressTracing.tspackages/vercel-edge/src/transports/index.tspackages/node-core/src/transports/http.ts
Environment
- Platform: Vercel Serverless (Node.js runtime)
- Framework: Next.js 15.4.9
- SDK: @sentry/nextjs 10.27.0 (also reproduced on 10.34.0)
- Database: Prisma 6.13.0
- Sample Rate:
tracesSampleRate: 1.0
Additional Context
No response
Priority
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it.
Metadata
Metadata
Assignees
Projects
Status