[GH-ISSUE #972] unstable_io() does not hang during prerendering #210

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

Originally created by @Divkix on GitHub (Apr 29, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/972

Summary

During prerendering contexts (static export, --prerender-all, TPR), unstable_io() should return a hanging promise to prevent execution past the IO boundary. Currently, vinext always returns a resolved promise, matching the browser/client implementation but not the server-side behavior.

Expected behavior (Next.js)

In Next.js's server-side implementation (packages/next/src/server/request/io.ts), unstable_io() branches on workUnitStore.type:

  • prerender / prerender-client / prerender-runtime → returns makeHangingPromise(renderSignal, route, reason) — stalls prerendering past the IO boundary
  • request → resolves immediately
  • cache / private-cache / unstable-cache / generate-static-params / prerender-legacy → resolves immediately

Current vinext behavior

packages/vinext/src/shims/cache.ts always returns _resolvedIOPromise — a singleton resolved promise. There is no prerendering context awareness.

Gap

vinext does not yet implement:

  1. workUnitAsyncStorage / workAsyncStorage with type tracking (request, prerender, cache, etc.)
  2. makeHangingPromise / renderSignal — the mechanism to stall prerendering
  3. RenderStage enum / staged-rendering module
  4. ppr-removed-error handling

These are foundational pieces needed not just for unstable_io() but for full prerendering and PPR parity.

  • vercel/next.js#92521 — Added unstable_io() API
  • vercel/next.js#92923 — Removed experimental flag guard
  • Next.js server impl: packages/next/src/server/request/io.ts
  • Next.js client impl: packages/next/src/client/request/io.browser.ts
Originally created by @Divkix on GitHub (Apr 29, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/972 ## Summary During prerendering contexts (static export, `--prerender-all`, TPR), `unstable_io()` should return a **hanging promise** to prevent execution past the IO boundary. Currently, vinext always returns a resolved promise, matching the browser/client implementation but not the server-side behavior. ## Expected behavior (Next.js) In Next.js's server-side implementation (`packages/next/src/server/request/io.ts`), `unstable_io()` branches on `workUnitStore.type`: - **`prerender` / `prerender-client` / `prerender-runtime`** → returns `makeHangingPromise(renderSignal, route, reason)` — stalls prerendering past the IO boundary - **`request`** → resolves immediately - **`cache` / `private-cache` / `unstable-cache` / `generate-static-params` / `prerender-legacy`** → resolves immediately ## Current vinext behavior `packages/vinext/src/shims/cache.ts` always returns `_resolvedIOPromise` — a singleton resolved promise. There is no prerendering context awareness. ## Gap vinext does not yet implement: 1. `workUnitAsyncStorage` / `workAsyncStorage` with type tracking (`request`, `prerender`, `cache`, etc.) 2. `makeHangingPromise` / `renderSignal` — the mechanism to stall prerendering 3. `RenderStage` enum / `staged-rendering` module 4. `ppr-removed-error` handling These are foundational pieces needed not just for `unstable_io()` but for full prerendering and PPR parity. ## Related PRs - [vercel/next.js#92521](https://github.com/vercel/next.js/pull/92521) — Added `unstable_io()` API - [vercel/next.js#92923](https://github.com/vercel/next.js/pull/92923) — Removed experimental flag guard - Next.js server impl: `packages/next/src/server/request/io.ts` - Next.js client impl: `packages/next/src/client/request/io.browser.ts`
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#210
No description provided.