[GH-ISSUE #958] Forward invalid dynamic usage errors on client-side navigations in dev #206

Closed
opened 2026-05-06 12:38:10 +02:00 by BreizhHardware · 0 comments

Originally created by @github-actions[bot] on GitHub (Apr 29, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/958

Next.js Change

In dev mode, the static shell validation only runs during the initial page load and HMR refreshes, not during client-side navigations. During a client-side navigation, an invalid dynamic usage error — for example a 'use cache' fill timeout, or a request API like cookies() called inside a 'use cache' scope — does still reach the browser via the errored 'use cache' stream. But when the cache invocation is wrapped in a user-space try/catch, the error is caught and swallowed in user code, and because the static shell validation isn't running to surface it separately, the error is then neither sent to the browser nor logged to the terminal.

This commit makes dev wait for the full render stream to finish when the validation is skipped, and then, if an error was recorded during the render, send it to the browser and log it to the terminal.

Commit: f5e54c0
PR: #93184

What Changed

In packages/next/src/server/app-render/app-render.tsx: when the static shell validation is skipped (e.g. on a client-side navigation in dev), the renderer now awaits the full render stream and, if any error was recorded during the render (including swallowed-by-user-try/catch errors that came back via the 'use cache' stream), forwards that error both to the browser dev overlay and to the terminal.

This mirrors what the static shell validation already does, and ensures we also catch errors from 'use cache' invocations that only run in the dynamic stage.

Impact on vinext

This is a developer-experience fix for App Router dev mode. vinext's App Router dev path (entries/app-rsc-entry.ts and the related dev SSR pipeline) needs to reproduce this behavior so that:

  1. Errors from 'use cache' scopes that misuse request APIs (e.g. cookies() inside 'use cache') surface during client-side navigations, not only on full page loads.
  2. User-space try/catch around a 'use cache' call doesn't silently swallow the error in dev — the dev server should still log it to the terminal and forward it to the browser overlay.

Without this, vinext's dev experience for 'use cache' and request-API misuse will silently diverge from Next.js: errors will appear on initial loads but disappear after a <Link> click.

Suggested Action

  • Review vinext's App Router dev render path for whether it runs (or can run) any equivalent of the static shell validation on client-side navigations.
  • If not, add a fallback path that, after the render stream finishes, checks for any recorded render-time error and propagates it to the dev overlay + terminal.
  • Add an e2e/dev test exercising a 'use cache' scope that throws (e.g. calls cookies()) and is wrapped in user try/catch, then navigated to via <Link>, asserting the error still surfaces.
Originally created by @github-actions[bot] on GitHub (Apr 29, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/958 ## Next.js Change In dev mode, the static shell validation only runs during the initial page load and HMR refreshes, not during client-side navigations. During a client-side navigation, an invalid dynamic usage error — for example a `'use cache'` fill timeout, or a request API like `cookies()` called inside a `'use cache'` scope — does still reach the browser via the errored `'use cache'` stream. But when the cache invocation is wrapped in a user-space `try`/`catch`, the error is caught and swallowed in user code, and because the static shell validation isn't running to surface it separately, the error is then neither sent to the browser nor logged to the terminal. This commit makes dev wait for the full render stream to finish when the validation is skipped, and then, if an error was recorded during the render, send it to the browser and log it to the terminal. **Commit:** [`f5e54c0`](https://github.com/vercel/next.js/commit/f5e54c06726b571a042fce67417e40a29f6b8689) **PR:** [#93184](https://github.com/vercel/next.js/pull/93184) ## What Changed In `packages/next/src/server/app-render/app-render.tsx`: when the static shell validation is skipped (e.g. on a client-side navigation in dev), the renderer now awaits the full render stream and, if any error was recorded during the render (including swallowed-by-user-`try`/`catch` errors that came back via the `'use cache'` stream), forwards that error both to the browser dev overlay and to the terminal. This mirrors what the static shell validation already does, and ensures we also catch errors from `'use cache'` invocations that only run in the dynamic stage. ## Impact on vinext This is a developer-experience fix for App Router dev mode. vinext's App Router dev path (`entries/app-rsc-entry.ts` and the related dev SSR pipeline) needs to reproduce this behavior so that: 1. Errors from `'use cache'` scopes that misuse request APIs (e.g. `cookies()` inside `'use cache'`) surface during client-side navigations, not only on full page loads. 2. User-space `try`/`catch` around a `'use cache'` call doesn't silently swallow the error in dev — the dev server should still log it to the terminal and forward it to the browser overlay. Without this, vinext's dev experience for `'use cache'` and request-API misuse will silently diverge from Next.js: errors will appear on initial loads but disappear after a `<Link>` click. ## Suggested Action - Review vinext's App Router dev render path for whether it runs (or can run) any equivalent of the static shell validation on client-side navigations. - If not, add a fallback path that, after the render stream finishes, checks for any recorded render-time error and propagates it to the dev overlay + terminal. - Add an e2e/dev test exercising a `'use cache'` scope that throws (e.g. calls `cookies()`) and is wrapped in user `try`/`catch`, then navigated to via `<Link>`, asserting the error still surfaces.
BreizhHardware 2026-05-06 12:38:10 +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#206
No description provided.