Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled
108 lines
3.8 KiB
Plaintext
108 lines
3.8 KiB
Plaintext
---
|
|
title: Cannot access `crypto.getRandomValue()`, `crypto.randomUUID()`, or another web or node crypto API that generates random values synchronously before other uncached data or Request data in a Server Component
|
|
---
|
|
|
|
## Why This Error Occurred
|
|
|
|
An API that produces a random value synchronously from the Web Crypto API or from Node's `crypto` package was used in a Server Component before accessing other uncached data through APIs like `fetch()` and native database drivers, or Request data through Next.js APIs like `cookies()`, `headers()`, `connection()` and `searchParams`. Accessing random values synchronously in this way interferes with the prerendering and prefetching capabilities of Next.js.
|
|
|
|
## Possible Ways to Fix It
|
|
|
|
If the random crypto value is appropriate to be prerendered and prefetched consider moving it into a Cache Component or Cache Function with the `"use cache"` directive.
|
|
|
|
If the random crypto value is intended to be generated on every user request consider whether an async API exists that achieves the same result. If not consider whether you can move the random crypto 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 crypto value generation with Request data access by using `await connection()`.
|
|
|
|
### Cache the token value
|
|
|
|
If you are generating a token to talk to a database that itself should be cached move the token generation inside the `"use cache"`.
|
|
|
|
Before:
|
|
|
|
```jsx filename="app/page.js"
|
|
async function getCachedData(token: string) {
|
|
"use cache"
|
|
return db.query(token, ...)
|
|
}
|
|
|
|
export default async function Page() {
|
|
const token = crypto.getRandomUUID()
|
|
const data = await getCachedData(token);
|
|
return ...
|
|
}
|
|
```
|
|
|
|
After:
|
|
|
|
```jsx filename="app/page.js"
|
|
async function getCachedData() {
|
|
"use cache"
|
|
const token = crypto.getRandomUUID()
|
|
return db.query(token, ...)
|
|
}
|
|
|
|
export default async function Page() {
|
|
const data = await getCachedData();
|
|
return ...
|
|
}
|
|
```
|
|
|
|
### Use an async API at request-time
|
|
|
|
If you require this random value to be unique per Request and an async version of the API exists switch to it instead. Also ensure that there is a parent Suspense boundary that defines a fallback UI Next.js can use while rendering this component on each Request.
|
|
|
|
Before:
|
|
|
|
```jsx filename="app/page.js"
|
|
import { generateKeySync } from 'node:crypto'
|
|
|
|
export default async function Page() {
|
|
const key = generateKeySync('hmac', { ... })
|
|
const digestedData = await digestDataWithKey(data, key);
|
|
return ...
|
|
}
|
|
```
|
|
|
|
After:
|
|
|
|
```jsx filename="app/page.js"
|
|
import { generateKey } from 'node:crypto'
|
|
|
|
export default async function Page() {
|
|
const key = await new Promise(resolve => generateKey('hmac', { ... }, key => resolve(key)))
|
|
const digestedData = await digestDataWithKey(data, key);
|
|
return ...
|
|
}
|
|
```
|
|
|
|
### Use `await connection()` at request-time
|
|
|
|
If you require this random value to be unique per Request and an async version of the API does not exist, call `await connection()`. Also ensure that there is a parent Suspense boundary that defines a fallback UI Next.js can use while rendering this component on each Request.
|
|
|
|
Before:
|
|
|
|
```jsx filename="app/page.js"
|
|
export default async function Page() {
|
|
const uuid = crypto.randomUUID()
|
|
return <RequestId id={uuid} />
|
|
}
|
|
```
|
|
|
|
After:
|
|
|
|
```jsx filename="app/page.js"
|
|
import { connection } from 'next/server'
|
|
|
|
export default async function Page() {
|
|
await connection()
|
|
const uuid = crypto.randomUUID()
|
|
return <RequestId id={uuid} />
|
|
}
|
|
```
|
|
|
|
## Useful Links
|
|
|
|
- [`connection` function](/docs/app/api-reference/functions/connection)
|
|
- [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
|
|
- [Node Crypto API](https://nodejs.org/docs/latest/api/crypto.html)
|
|
- [`Suspense` React API](https://react.dev/reference/react/Suspense)
|