Files
next.js/errors/next-prerender-runtime-random.mdx
T
Josh StoryandGitHub d86e197728 Support configuring a default instant validation level (#93301)
Adds `experimental.instantInsights.validationLevel` so an app can opt
into instant validation for all routes by default.

There are two public levels
* `manual-warning`: currently the default. this mode won't enable
instant validation except where you add `export const unstable_instant =
true` into your Layouts, Pages, and Default files
* `warning`: This mode will enable instant validation for all Page and
Default files. You can override this with `export const unstable_instant
= false` in Layouts, Pages, and Default files to tune what navigations
are validated.

In addition this change disables build time validation.

There is a now undocumented way to get back to running build validation
with
* `experimental-error`
* `experimental-manual-error`

The build validation isn't ready for users because we need to overhaul
the setup where you provide cookies and other sample values so we can
run validation without a live session like we do in dev.

To further support this the two remaining object properties that are
also not ready for active use, `samples` and `from` are being updated to
`unstable_samples` and `unstable_from` respectively.

We will continue to iterate on build time validation but may remove
these APIs or alter their semantics as we figure out a more ergonomic
way to support this setup.

In anticipation of multiple levels the object form of `instant` can be
provided a level value `warning` or `experimental-error`. this latter
option is similarly undocumented so documented behavior will only cover
`warning` which is generally a synonym of true unless you are activating
error by default
2026-05-06 10:37:50 -07:00

109 lines
4.7 KiB
Plaintext

---
title: Cannot access `Math.random()` before other uncached data or `connection()` in a Server Component
---
## Why This Error Occurred
`Math.random()` was called in a Server Component before accessing other uncached data through APIs like `fetch()` and native database drivers, or the `connection()` API. While typically random values can be guarded behind Runtime data like `cookies()`, `headers()`, `params`, and `searchParams`, this particular route is configured for Runtime Prefetching which makes these APIs available as part of the prefetch request. Accessing random values without preceding it with uncached data or `await connection()` interferes with the framework's ability to produce a correct prefetch result.
## Possible Ways to Fix It
If the random value is appropriate to be prefetched consider moving it into a Cache Component or Cache Function with the `"use cache"` directive.
If the random value is intended to be generated on every user navigation consider whether you can move the random value generation later, behind other existing uncached data or Request data access. If there is no way to do this you can always precede the random value generation with Request data access by using `await connection()`.
If the random value is being used as a unique identifier for diagnostic purposes such as logging or tracking consider using an alternate method of id generation that does not rely on random number generation such as incrementing an integer.
> **Note**: Sometimes the place that generates a random value synchronously is inside 3rd party code. While you can't easily replace the `Math.random()` call directly, the other strategies can be applied in your own project code regardless of how deep random generation is.
### Cache the random value
If your random value is cacheable, move the `Math.random()` call to a `"use cache"` function. For instance, imagine you have a product page and you want to randomize the product order periodically but you are fine with the random order being re-used for different users.
Before:
```jsx filename="app/page.js"
export const unstable_prefetch = 'force-runtime'
export default async function Page({ params }) {
const { category } = await params
const products = await getCachedProducts(category)
const randomSeed = Math.random()
const randomizedProducts = randomize(products, randomSeed)
return <ProductsView products={randomizedProducts} />
}
```
After:
```jsx filename="app/page.js"
export const unstable_prefetch = 'force-runtime'
async function RandomizedProductsView({ category }) {
'use cache'
const products = await getCachedProducts(category)
const randomSeed = Math.random()
const randomizedProducts = randomize(products, randomSeed)
return <ProductsView products={randomizedProducts} />
}
export default async function Page({ params }) {
const { category } = await params
return <RandomizedProductsView category={category} />
}
```
> **Note**: `"use cache"` is a powerful API with some nuances. If your cache lifetime is too short Next.js may still exclude it from prerendering. Check out the docs for `"use cache"` to learn more.
### Indicate the random value is unique per Request
If you want the random value to be evaluated on each Request precede it with `await connection()`. Next.js will exclude this Server Component from the prerendered HTML and include the fallback UI from the nearest Suspense boundary wrapping this component instead. When a user makes a Request for this page the Server Component will be rendered and the updated UI will stream in dynamically.
Before:
```jsx filename="app/page.js"
export const unstable_prefetch = 'force-runtime'
export default async function Page({ params }) {
const { category } = await params
const products = await getCachedProducts(category)
const randomSeed = Math.random()
const randomizedProducts = randomize(products, randomSeed)
return <ProductsView products={randomizedProducts} />
}
```
After:
```jsx filename="app/page.js"
export const unstable_prefetch = 'force-runtime'
import { connection } from 'next/server'
async function ProductsSkeleton() {
...
}
export default async function Page({ params }) {
const { category } = await params
const products = await getCachedProducts(category);
return (
<Suspense fallback={<ProductsSkeleton />}>
<DynamicProductsView products={products} />
</Suspense>
)
}
async function DynamicProductsView({ products }) {
await connection();
const randomSeed = Math.random()
const randomizedProducts = randomize(products, randomSeed)
return <ProductsView products={randomizedProducts} />
}
```
## Useful Links
- [`connection` function](/docs/app/api-reference/functions/connection)
- [`Suspense` React API](https://react.dev/reference/react/Suspense)