Description
React version: 19.1.0
I've tried hard to create a minimal reproduction for this one with just React and failed, but for reasons I'll describe I still suspect this might be a React bug and not only a Next.js one.
There are several reproductions over in the Next.js repo: #63121 #63388 #78396 #80483
This one is very, very hard to describe so sorry for a lengthy post. In essence, I think there are situations where transitions changing out a currently pending promise passed to use
results in "Rendered too many hooks" being thrown, even when there are no conditional hooks or early returns.
This is not enough however, there seems to be some extra secret ingredient that is required to trigger this which I have not found, maybe incremental hydration?
Why I think this is a bug
This is happening in code paths where there are no conditional hooks being rendered. (Well, there is in the Next case, but it's a NODE_ENV
check and the bug happens even when that is removed)
Besides the Next.js reproductions, which vary in how they trigger the bug, I've also seen this happen on a separate code path in our repo, in user land-code where there are also no conditional hooks or early returns. That code path also has two possible Suspends in the same custom hook. This also uses the Next app router, but unlike the reproductions above, the stack trace does not lead to Next.js internals. This internal bug is very hard to reproduce consistently unfortunately.
Some debugging details
- I have been debugging #78396 with a local Next.js build
- The bug is triggered on this line in
app-router.tsx
, but the actual error seems to stem from this line inuseActionQueue
(?)return isThenable(state) ? use(state) : state
- I removed the
if (process.env.NODE_ENV !== 'production') {
conditional hook case just to be sure - I added a few logs to
useActionQueue
, when the bug triggers this is what has happened:
- That is, a server action is still pending when a redirect happens
- The error happen when the redirect fulfills
- If the server action is removed, bug goes away
- If I add enough delay for the
redirect
so the server action has time to finish, the bug goes away, that is, this is fine:
- I have also added a breakpoint to the error itself inside of
updateWorkInProgressHook
currentHook
exists but does not have a.next
workInProgressHook
exists but does not have a.next
- This is the stack trace, from
beginWork
:
I know this is very fuzzy and I'm sorry I don't have more details, but this is where my React debugging skills runs out and I still wanted to report it as there is some good evidence at least part of this bug lies on the React side of things.
I'm happy to provide whatever more details I can help with.