Fetch with setTimeout fails during prerendering?
I'm getting this error at build time when prerendering some of the pages defined in the generateStaticParams:
Error: During prerendering, fetch() rejects when the prerender is complete. Typically these errors are handled by React but if you move fetch() to a different context by using setTimeout, after, or similar functions you may observe this error and you should handle it in that context.
This means the page can't have a fetch with exponential backoffs because the implementation uses setTimeout?
This is a good question about how prerendering works in Next.js. Let me search the codebase to understand the error message and the constraints around fetch during prerendering.
Let me try a broader search:
Perfect! Now let me look at the dynamic-rendering-utils.ts file to understand the context:
Now let me look at the test case to understand how this error manifests:
Let me check the test fixtures to see what scenarios trigger this:
Now let me search for how fetch is specifically handled during prerendering:
Let me look at the patch-fetch.ts file since that's where fetch is being patched:
Let me continue reading to find where fetch is being handled during prerendering:
Perfect! Now I can see how it works. Let me search for documentation about this behavior:
Let me check the errors documentation:
Based on my exploration of the Next.js codebase, I can now answer your question clearly:
##Summary
Yes, you've correctly identified the issue. The error you're seeing means that your page cannot use fetch() with exponential backoff retry logic that relies on setTimeout when prerendering.
##What's happening
During prerendering (static generation), Next.js uses a mechanism called "hanging promises" to track dynamic API usage. Here's how it works:
-
When your page prerendering completes, Next.js triggers an
AbortSignalthat causes all pending requests (likefetch()calls) to immediately reject with the error you're seeing. -
The problem with exponential backoff: If your retry logic uses
setTimeoutto delay the next fetch attempt:- The first
fetch()happens during prerendering - The prerendering completes, triggering the abort signal
- Your
setTimeoutcallback fires later and tries to callfetch()again - But by then, prerendering is complete, so the new
fetch()immediately rejects with your error
- The first
-
Why React can normally handle this: React has built-in error boundaries that would normally catch these rejections, but since you've moved the code into a different async context via
setTimeout, React can't catch it, and you see the unhandled error.
##Code location
From the source code (packages/next/src/server/lib/patch-fetch.ts lines 552 and 678), when Next.js detects a dynamic fetch requirement during prerendering, it returns:
return makeHangingPromise<Response>(
workUnitStore.renderSignal,
workStore.route,
'fetch()'
)
This creates a promise that always rejects when prerendering is complete, regardless of when you try to await it.
##Solutions
- Move retry logic outside of prerendering: Use
revalidateTag()or on-demand revalidation instead of runtime retries - Use
unstable_noStore(): Mark the page as dynamic so it doesn't prerender - Handle the error properly: If you must retry, catch the error in the same async context where it occurs, not in a deferred callback
- Use server-side caching: Cache successful responses and avoid retry logic during static generation
END OF POST
Claude Haiku 4.5