[PR #352] [MERGED] fix(app-router): don't clear RSC context before lazy stream is consumed #503

Closed
opened 2026-05-06 13:08:25 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/352
Author: @james-elicx
Created: 3/8/2026
Status: Merged
Merged: 3/8/2026
Merged by: @james-elicx

Base: mainHead: j-branch-8


📝 Commits (2)

  • c0a2435 fix(app-router): don't clear RSC context before lazy stream is consumed
  • af053d6 fix(app-router): remove premature context clears from server action and intercepting route RSC branches

📊 Changes

5 files changed (+214 additions, -9 deletions)

View changed files

📝 packages/vinext/src/server/app-dev-server.ts (+21 -9)
tests/fixtures/app-basic/app/nextjs-compat/rsc-context-lazy-stream/layout.tsx (+28 -0)
tests/fixtures/app-basic/app/nextjs-compat/rsc-context-lazy-stream/not-found.tsx (+19 -0)
tests/fixtures/app-basic/app/nextjs-compat/rsc-context-lazy-stream/page.tsx (+15 -0)
tests/nextjs-compat/rsc-context-lazy-stream.test.ts (+131 -0)

📄 Description

When handling RSC requests (client-side navigation), the handler was calling setNavigationContext(null) and setHeadersContext(null) immediately after renderToReadableStream() returned — before the stream was actually consumed.

The problem: renderToReadableStream() returns as soon as the shell is ready, but the stream is consumed lazily by the client. Async server components that run during stream consumption (e.g. NextIntlClientProviderServer, which is rendered as a child of NextIntlClientProvider in a layout) would execute after the handler had already cleared context, causing them to see null headers/navigation context and throw. The symptom for users was useTranslations() failing with "context from NextIntlClientProvider was not found" during client-side navigation.

Fix: Remove the early setNavigationContext(null) / setHeadersContext(null) calls on the RSC response branches in renderHTTPAccessFallbackPage and renderErrorBoundaryPage. Context is already cleaned up correctly when the AsyncLocalStorage scope from runWithHeadersContext unwinds — no manual clear is needed.

The HTML response branches are unaffected: those await the full SSR pipeline (handleSsr) before responding, so context is fully consumed by the time the clears run.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/352 **Author:** [@james-elicx](https://github.com/james-elicx) **Created:** 3/8/2026 **Status:** ✅ Merged **Merged:** 3/8/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `j-branch-8` --- ### 📝 Commits (2) - [`c0a2435`](https://github.com/cloudflare/vinext/commit/c0a2435f895dc9e3dbe4f45950476688755ae50d) fix(app-router): don't clear RSC context before lazy stream is consumed - [`af053d6`](https://github.com/cloudflare/vinext/commit/af053d6d1f879688dc0b7b8fedd4592a28d97fa3) fix(app-router): remove premature context clears from server action and intercepting route RSC branches ### 📊 Changes **5 files changed** (+214 additions, -9 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/server/app-dev-server.ts` (+21 -9) ➕ `tests/fixtures/app-basic/app/nextjs-compat/rsc-context-lazy-stream/layout.tsx` (+28 -0) ➕ `tests/fixtures/app-basic/app/nextjs-compat/rsc-context-lazy-stream/not-found.tsx` (+19 -0) ➕ `tests/fixtures/app-basic/app/nextjs-compat/rsc-context-lazy-stream/page.tsx` (+15 -0) ➕ `tests/nextjs-compat/rsc-context-lazy-stream.test.ts` (+131 -0) </details> ### 📄 Description When handling RSC requests (client-side navigation), the handler was calling `setNavigationContext(null)` and `setHeadersContext(null)` immediately after `renderToReadableStream()` returned — before the stream was actually consumed. The problem: `renderToReadableStream()` returns as soon as the shell is ready, but the stream is consumed *lazily* by the client. Async server components that run *during* stream consumption (e.g. `NextIntlClientProviderServer`, which is rendered as a child of `NextIntlClientProvider` in a layout) would execute after the handler had already cleared context, causing them to see null headers/navigation context and throw. The symptom for users was `useTranslations()` failing with "context from NextIntlClientProvider was not found" during client-side navigation. **Fix:** Remove the early `setNavigationContext(null)` / `setHeadersContext(null)` calls on the RSC response branches in `renderHTTPAccessFallbackPage` and `renderErrorBoundaryPage`. Context is already cleaned up correctly when the `AsyncLocalStorage` scope from `runWithHeadersContext` unwinds — no manual clear is needed. The HTML response branches are unaffected: those `await` the full SSR pipeline (`handleSsr`) before responding, so context is fully consumed by the time the clears run. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:08:25 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#503
No description provided.