Skip to content

feat(react-router): Support renderToReadableStream in createSentryHandleRequest - #25254

Open
lfantone wants to merge 4 commits into
getsentry:developfrom
lfantone:feat/react-router-web-stream-handle-request
Open

lfantone wants to merge 4 commits into
getsentry:developfrom
lfantone:feat/react-router-web-stream-handle-request

Conversation

@lfantone

Copy link
Copy Markdown

Adds a Web Streams variant of createSentryHandleRequest, so apps on renderToReadableStream (non-Node runtimes, or Node with unstable_enableNodeReadableStream) no longer have to hand-compose wrapSentryHandleRequest and injectTraceMetaTags.

Following the constraints from the discussion on the issue to keep it non-breaking:

  • SentryHandleRequestOptions and the Node path are untouched. The Web options are a separate type, accepted through an overload and only used when renderToReadableStream is passed in.
  • The Web handler lives in its own module with no Node imports, and is exported from the cloudflare entry as well as the server entry. Otherwise it would only help Node apps. No new runtime imports or peer dependencies.
  • A </head> split across chunks was previously missed by both transformers. A shared helper now holds back only a trailing partial </head> (rather than a fixed number of characters) and flushes it at the end of the stream, so it adds as little streaming delay as possible. It is used by getMetaTagTransformer (Node) and injectTraceMetaTags (Web).
  • injectTraceMetaTags moved to a Node-free module and is still re-exported from /cloudflare, so the public API is unchanged.
  • The react-router-8-framework cloudflare e2e entry now uses the new API instead of a hand-written copy of it.

Fixes #25168

@chargome chargome left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall looks good already, will trigger ci

Comment thread packages/react-router/src/server/createSentryHandleRequestWebStream.tsx Outdated
Comment thread packages/react-router/src/server/createSentryHandleRequest.tsx Outdated
@lfantone

Copy link
Copy Markdown
Author

The hydrogen e2e failure was a regression from this PR: the trace tags were resolved inside the stream transform, which workerd runs outside the request context. They're now resolved up front. Fixed in 424465d.

@lfantone
lfantone force-pushed the feat/react-router-web-stream-handle-request branch 3 times, most recently from da1cd76 to aa51022 Compare October 14, 2026 06:59
@lfantone
lfantone marked this pull request as ready for review October 14, 2026 09:17
@lfantone
lfantone requested a review from a team as a code owner October 14, 2026 09:17
@lfantone
lfantone requested review from mydea and s1gr1d and removed request for a team October 14, 2026 09:17
@lfantone
lfantone force-pushed the feat/react-router-web-stream-handle-request branch from aa51022 to c6da107 Compare October 14, 2026 09:17

@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 packages/react-router/src/server/createSentryHandleRequestWebStream.tsx Outdated
@lfantone
lfantone force-pushed the feat/react-router-web-stream-handle-request branch from 83f7782 to c28aa9c Compare October 14, 2026 13:25
…dleRequest

Adds a Web Streams variant of createSentryHandleRequest, accepted through an overload and exported from the cloudflare entry, and handles a </head> tag split across chunks in both the Node and Web transformers.

Closes getsentry#25168
…types

Resolve the trace meta tags when injectTraceMetaTags is called instead of inside the stream transform. Runtimes such as workerd run the transform outside the request's async context, where no trace data is available, so the tags were silently dropped.

Also let allReady rejections propagate for bots and SPA mode, and move the handler types shared by the Node and Web Streams handlers into their own module.
…ceMetaTags

workerd only supports a custom TransformStream transformer from compatibility date 2024-11-11, and Hydrogen's MiniOxygen runs with an older one, so the constructor threw and no trace meta tags were injected. Use a ReadableStream with a pull handler instead, as before, while keeping the shared </head> handling.
The abort timer can run on Node through renderToReadableStream, where a timer that is not unref'd can keep the process alive until streamTimeout while a render is still pending.
@lfantone
lfantone force-pushed the feat/react-router-web-stream-handle-request branch from c28aa9c to b7f8d1f Compare October 14, 2026 17:58

@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.

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 b7f8d1f. Configure here.

try {
body = await renderToReadableStream(app, {
nonce,
signal: controller.signal,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Render ignores request abort signal

Medium Severity

The Web handler aborts renderToReadableStream only through an internal streamTimeout controller and never links that render signal to request.signal. Client disconnects and platform cancellations therefore keep rendering until the timeout, which burns Cloudflare Worker CPU and drops the abort behavior that the official renderToReadableStream template and the previous hand-written handler used.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b7f8d1f. Configure here.

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

external PR from an external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(react-router): support renderToReadableStream in createSentryHandleRequest

2 participants