There's a bug in a nested Suspense where the inner fallback itself suspends (via use() on a delay promise), and the inner content resolves before the fallback. Fizz mis-tracks boundary segments during the transition from "pending with suspended fallback" to "completed."
This is a useful pattern for when you want to create a DeferredSuspense boundary that blocks for a pre-set amount of time and then flushes. If the period passes and the children have not un-suspended, we flush the alternate boundary to the client.
I am aware this a cursed use of suspense, but it should be valid imo.
React version: 19.2.4
Steps To Reproduce
$ node nested-suspense-bug-repro.mjs
Link to code example:
https://gist.github.com/switz/45d7c9f49953e11de7eec9d737841e2e#file-nested-suspense-bug-repro-mjs
The current behavior
$ node nested-suspense-bug-repro.mjs
onError: A previously unvisited boundary must have exactly one root segment. This is a bug in React.
Bug triggered: A previously unvisited boundary must have exactly one root segment. This is a bug in React.
The expected behavior
When content resolves FAST (before ms):
- No fallback is ever shown — content renders directly
When content resolves SLOW (after ms):
- For the first ms milliseconds, nothing visible changes (outer Suspense holds)
- After ms, the fallback appears (inner Suspense fallback delay resolves, outer Suspense can now show its
content which includes the pending inner boundary with its fallback)
- When content finally resolves, it replaces the fallback via streaming
The basic mechanics:
<Suspense fallback={fallback}> ← outer: catches if inner fallback suspends
<Suspense fallback={<Delay ms={200}>{fallback}</Delay>}> ← inner: delay on fallback
{children} ← the actual async content
</Suspense>
</Suspense>
- Children suspend → inner Suspense tries its fallback
- Fallback has which also suspends → outer Suspense catches both
- If children resolve before 200ms → inner boundary completes, outer shows content directly (no fallback
flash)
- If 200ms elapses first → delay resolves, outer can now render (shows inner's fallback), children
stream in later
The bug is in case 3 — Fizz crashes instead of rendering the content directly.
There's a bug in a nested Suspense where the inner fallback itself suspends (via use() on a delay promise), and the inner content resolves before the fallback. Fizz mis-tracks boundary segments during the transition from "pending with suspended fallback" to "completed."
This is a useful pattern for when you want to create a
DeferredSuspenseboundary that blocks for a pre-set amount of time and then flushes. If the period passes and the children have not un-suspended, we flush the alternate boundary to the client.I am aware this a cursed use of suspense, but it should be valid imo.
React version: 19.2.4
Steps To Reproduce
$ node nested-suspense-bug-repro.mjsLink to code example:
https://gist.github.com/switz/45d7c9f49953e11de7eec9d737841e2e#file-nested-suspense-bug-repro-mjs
The current behavior
The expected behavior
When content resolves FAST (before ms):
When content resolves SLOW (after ms):
content which includes the pending inner boundary with its fallback)
The basic mechanics:
flash)
stream in later
The bug is in case 3 — Fizz crashes instead of rendering the content directly.