Skip to content

fix(middleware-sentry): propagate and continue sender trace across runs - #1882

Open
princejain756 wants to merge 1 commit into
inngest:mainfrom
princejain756:fix/sentry-continue-sender-trace
Open

princejain756 wants to merge 1 commit into
inngest:mainfrom
princejain756:fix/sentry-continue-sender-trace

Conversation

@princejain756

Copy link
Copy Markdown

Fixes #1807 (EXE-2292)

wrapRequest in @inngest/middleware-sentry always built a synthetic sentry-trace header from ulidToTraceId(runId), so events dispatched inside an active Sentry span started an isolated trace instead of continuing the sender's trace.

This adds transformSendEvent and transformStepInput hooks to attach active sentry-trace and baggage data onto outgoing events, strips the internal carrier key in transformFunctionInput so user handlers still receive clean event.data, and updates wrapRequest to continue the sender's trace from the incoming request headers or event payload when present (falling back to ulidToTraceId(runId) when no sender trace exists or when continueSenderTrace: false is configured).

Closes inngest#1807

Previously `wrapRequest` always synthesized a `sentry-trace` header from `ulidToTraceId(runId)`, so events dispatched inside an active Sentry span started an isolated trace instead of continuing the sender's trace. This adds `transformSendEvent` and `transformStepInput` hooks to propagate active `sentry-trace` and `baggage` data onto outgoing events, strips the internal carrier in `transformFunctionInput`, and updates `wrapRequest` to continue the sender's trace when present (configurable via `continueSenderTrace`, defaulting to `true`).
@changeset-bot

changeset-bot Bot commented Nov 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a9ca664

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@inngest/middleware-sentry Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@greptile-apps

greptile-apps Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 3/5

[Medium impact] The change affects trace reporting for users of the Sentry middleware.

Fix incoming HTTP trace headers and waiting-event cleanup before merging.

Findings

  1. P1 HTTP trace headers are lost ▶
  2. P1 Waiting events keep internal data ▶
Fix with agent prompt
### Issue 1
packages/middleware-sentry/src/middleware.ts:619-622
Incoming `sentry-trace` headers never reach this branch through the HTTP adapter. `requestInfo.headers` comes from `getHeaders()`, which builds response headers and forwards only `traceparent` and `tracestate`. A request with a valid Sentry header but no event carrier therefore starts a separate trace.

Read the original request headers through the adapter, or expose them through `requestInfo`. The new test calls `wrapRequest` directly, so it misses this failure.

### Issue 2
packages/middleware-sentry/src/middleware.ts:530-532
Adding the carrier to every outgoing event also changes events returned by `step.waitForEvent()`. The new cleanup only covers `ctx.event` and `ctx.events`, not step results. A waiting function therefore receives `__inngest_sentry_trace` in its business data. If its `EventType` schema rejects extra fields, the engine rejects the result before returning it to the handler.

Keep the carrier outside business data, or strip it from waiting-event results before the engine checks their schemas.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR carries Sentry trace data on outgoing events and uses it to continue traces in triggered runs.

  • Triggered function runs can continue the sender’s Sentry trace.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Active Sentry trace] --> B[Send event or invoke function]
  B --> C[Add carrier to event data]
  C --> D[Triggered function]
  D --> E[Continue trace and strip carrier]
  C --> F[Waiting function]
  F --> G[Carrier remains in step result]
Loading

Reviews (1) · Last reviewed commit: "fix(middleware-sentry): propagate and co..." · Reviewed by Greptile

Comment on lines +619 to +622
if (isRecord(requestInfo.headers)) {
let headerSentryTrace: string | undefined;
let headerBaggage: string | undefined;
for (const [key, value] of Object.entries(requestInfo.headers)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 HTTP trace headers are lost

Incoming sentry-trace headers never reach this branch through the HTTP adapter. requestInfo.headers comes from getHeaders(), which builds response headers and forwards only traceparent and tracestate. A request with a valid Sentry header but no event carrier therefore starts a separate trace.

Read the original request headers through the adapter, or expose them through requestInfo. The new test calls wrapRequest directly, so it misses this failure.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/middleware-sentry/src/middleware.ts
Line: 619-622

Comment:
**HTTP trace headers are lost**

Incoming `sentry-trace` headers never reach this branch through the HTTP adapter. `requestInfo.headers` comes from `getHeaders()`, which builds response headers and forwards only `traceparent` and `tracestate`. A request with a valid Sentry header but no event carrier therefore starts a separate trace.

Read the original request headers through the adapter, or expose them through `requestInfo`. The new test calls `wrapRequest` directly, so it misses this failure.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +530 to +532
data: {
...existingData,
[SENTRY_TRACE_DATA_KEY]: traceData,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Waiting events keep internal data

Adding the carrier to every outgoing event also changes events returned by step.waitForEvent(). The new cleanup only covers ctx.event and ctx.events, not step results. A waiting function therefore receives __inngest_sentry_trace in its business data. If its EventType schema rejects extra fields, the engine rejects the result before returning it to the handler.

Keep the carrier outside business data, or strip it from waiting-event results before the engine checks their schemas.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/middleware-sentry/src/middleware.ts
Line: 530-532

Comment:
**Waiting events keep internal data**

Adding the carrier to every outgoing event also changes events returned by `step.waitForEvent()`. The new cleanup only covers `ctx.event` and `ctx.events`, not step results. A waiting function therefore receives `__inngest_sentry_trace` in its business data. If its `EventType` schema rejects extra fields, the engine rejects the result before returning it to the handler.

Keep the carrier outside business data, or strip it from waiting-event results before the engine checks their schemas.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

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.

middleware-sentry: runs never continue the sender's trace

1 participant