Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion packages/next/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -1284,5 +1284,27 @@
"1283": "Cache Components error recovery expected an original Flight prerender result",
"1284": "Cache Components error recovery expected an original prerender store",
"1285": "Cache Components error recovery expected an original resume data cache",
"1286": "Route \"%s\": Could not validate that a segment in your UI has instant navigation."
"1286": "Route \"%s\": Could not validate that a segment in your UI has instant navigation.",
"1287": "\\`cacheLife()\\` can only be called inside a \\`\"use cache\"\\` function.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/cacheLife",
"1288": "\\`\"use cache: private\"\\` needs an active request. It can't be used during \\`generateStaticParams\\` or other build-time contexts.\\nLearn more: https://nextjs.org/docs/app/api-reference/directives/use-cache-private",
"1289": "Route \"%s\": \\`searchParams\\` can't be read inside \\`\"use cache\"\\`. Await it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1290": "Route \"%s\": \\`cookies()\\` can't be read inside \\`unstable_cache()\\`. Read it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/unstable_cache",
"1291": "\\`cacheTag()\\` can only be called inside a \\`\"use cache\"\\` function.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/cacheTag",
"1292": "Route \"%s\": \\`headers()\\` can't be read inside \\`\"use cache\"\\`. Read it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1293": "\\`\"use cache: private\"\\` can't be nested inside \\`\"use cache\"\\`. It can only be nested inside another \\`\"use cache: private\"\\`.\\nLearn more: https://nextjs.org/docs/app/api-reference/directives/use-cache-private",
"1294": "Route \"%s\": \\`%s\\` can't be called inside \\`\"use cache\"\\`. Revalidation must run outside renders and cached functions so caches stay consistent.\\nLearn more: https://nextjs.org/docs/app/getting-started/revalidating",
"1295": "\\`\"use cache: private\"\\` can't be used inside \\`unstable_cache()\\`.\\nLearn more: https://nextjs.org/docs/app/api-reference/directives/use-cache-private",
"1296": "Route \"%s\": \\`%s\\` can't be called inside \\`unstable_cache()\\`. Draft mode can be read from a cached function, but enabling or disabling it must happen outside.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/unstable_cache",
"1297": "Route \"%s\": \\`%s\\` can't be read inside \\`unstable_cache()\\`. Read it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/unstable_cache",
"1298": "Route \"%s\": \\`cookies()\\` can't be read inside \\`\"use cache\"\\`. Read it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1299": "Route \"%s\": \\`%s\\` can't be called inside \\`unstable_cache()\\`. Revalidation must run outside renders and cached functions so caches stay consistent.\\nLearn more: https://nextjs.org/docs/app/getting-started/revalidating",
"1300": "Route \"%s\": \\`connection()\\` can't be used inside \\`unstable_cache()\\`. A cache entry can be built before any request exists, so it can't depend on one.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/unstable_cache",
"1301": "Route \"%s\": \\`%s\\` can't be read inside \\`\"use cache\"\\`. Read it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1302": "Route \"%s\": \\`%s\\` can't be called inside \\`\"use cache\"\\`. Draft mode can be read from a cached function, but enabling or disabling it must happen outside.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1303": "Route \"%s\": \\`headers()\\` can't be read inside \\`unstable_cache()\\`. Read it outside the cached function and pass what you need as an argument.\\nLearn more: https://nextjs.org/docs/app/api-reference/functions/unstable_cache",
"1304": "Route \"%s\": \\`connection()\\` can't be used inside \\`\"use cache: private\"\\`. A private cache entry can be built before a navigation request, so it can't depend on one.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1305": "Route \"%s\": \\`connection()\\` can't be used inside \\`\"use cache\"\\`. A cache entry can be built before any request exists, so it can't depend on one.\\nLearn more: https://nextjs.org/docs/messages/next-request-in-use-cache",
"1306": "This \"use cache\" has a dynamic cache life that was propagated to its parent.\nLearn more: https://nextjs.org/docs/messages/nested-use-cache-no-explicit-cachelife",
"1307": "A nested \\`\"use cache\"\\` with a short \\`expire\\` (under 5 minutes) is inside an outer \\`\"use cache\"\\` that has no \\`cacheLife()\\`. Add \\`cacheLife()\\` to the outer one to choose: a longer \\`expire\\` to prerender it, or a short \\`expire\\` to keep it dynamic.\\nLearn more: https://nextjs.org/docs/messages/nested-use-cache-no-explicit-cachelife",
"1308": "A nested \\`\"use cache\"\\` with \\`revalidate: 0\\` is inside an outer \\`\"use cache\"\\` that has no \\`cacheLife()\\`. Add \\`cacheLife()\\` to the outer one to choose: a non-zero \\`revalidate\\` to prerender it, or \\`revalidate: 0\\` to keep it dynamic.\\nLearn more: https://nextjs.org/docs/messages/nested-use-cache-no-explicit-cachelife"
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ export const styles = `
}

.error-cause-message {
margin: 0;
margin-left: 4px;
margin: 0 0 16px 4px;
color: var(--color-red-900);
font-weight: 500;
font-size: var(--size-16);
Expand Down
17 changes: 8 additions & 9 deletions packages/next/src/server/request/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import { isRequestAPICallableInsideAfter } from './utils'
import { applyOwnerStack } from '../dynamic-rendering-utils'
import { RenderStage } from '../app-render/staged-rendering'
import { InvariantError } from '../../shared/lib/invariant-error'
import {
createConnectionInPublicUseCacheError,
createConnectionInPrivateUseCacheError,
createConnectionInUnstableCacheError,
} from '../use-cache/use-cache-messages'

/**
* This function allows you to indicate that you require an actual user Request before continuing.
Expand Down Expand Up @@ -54,9 +59,7 @@ export function connection(): Promise<void> {
if (workUnitStore) {
switch (workUnitStore.type) {
case 'cache': {
const error = new Error(
`Route ${workStore.route} used \`connection()\` inside "use cache". The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual request, but caches must be able to be produced before a request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
)
const error = createConnectionInPublicUseCacheError(workStore.route)
Error.captureStackTrace(error, connection)
applyOwnerStack(error)
workStore.invalidDynamicUsageError ??= error
Expand All @@ -66,18 +69,14 @@ export function connection(): Promise<void> {
// It might not be intuitive to throw for private caches as well, but
// we don't consider runtime prefetches as "actual requests" (in the
// navigation sense), despite allowing them to read cookies.
const error = new Error(
`Route ${workStore.route} used \`connection()\` inside "use cache: private". The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual navigation request, but caches must be able to be produced before a navigation request, so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
)
const error = createConnectionInPrivateUseCacheError(workStore.route)
Error.captureStackTrace(error, connection)
applyOwnerStack(error)
workStore.invalidDynamicUsageError ??= error
throw error
}
case 'unstable-cache':
throw new Error(
`Route ${workStore.route} used \`connection()\` inside a function cached with \`unstable_cache()\`. The \`connection()\` function is used to indicate the subsequent code must only run when there is an actual Request, but caches must be able to be produced before a Request so this function is not allowed in this scope. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
)
throw createConnectionInUnstableCacheError(workStore.route)
case 'generate-static-params':
throw new Error(
`Route ${workStore.route} used \`connection()\` inside \`generateStaticParams\`. This is not supported because \`generateStaticParams\` runs at build time without an HTTP request. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context`
Expand Down
12 changes: 6 additions & 6 deletions packages/next/src/server/request/cookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import { isRequestAPICallableInsideAfter } from './utils'
import { applyOwnerStack } from '../dynamic-rendering-utils'
import { InvariantError } from '../../shared/lib/invariant-error'
import { RenderStage } from '../app-render/staged-rendering'
import {
createCookiesInUseCacheError,
createCookiesInUnstableCacheError,
} from '../use-cache/use-cache-messages'

export function cookies(): Promise<ReadonlyRequestCookies> {
const callingExpression = 'cookies'
Expand Down Expand Up @@ -65,17 +69,13 @@ export function cookies(): Promise<ReadonlyRequestCookies> {
if (workUnitStore) {
switch (workUnitStore.type) {
case 'cache':
const error = new Error(
`Route ${workStore.route} used \`cookies()\` inside "use cache". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`cookies()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
)
const error = createCookiesInUseCacheError(workStore.route)
Error.captureStackTrace(error, cookies)
applyOwnerStack(error)
workStore.invalidDynamicUsageError ??= error
throw error
case 'unstable-cache':
throw new Error(
`Route ${workStore.route} used \`cookies()\` inside a function cached with \`unstable_cache()\`. Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`cookies()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
)
throw createCookiesInUnstableCacheError(workStore.route)
case 'generate-static-params':
throw new Error(
`Route ${workStore.route} used \`cookies()\` inside \`generateStaticParams\`. This is not supported because \`generateStaticParams\` runs at build time without an HTTP request. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context`
Expand Down
14 changes: 10 additions & 4 deletions packages/next/src/server/request/draft-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import { StaticGenBailoutError } from '../../client/components/static-generation
import { DynamicServerError } from '../../client/components/hooks-server-context'
import { InvariantError } from '../../shared/lib/invariant-error'
import { delayUntilRuntimeStage } from '../dynamic-rendering-utils'
import {
createDraftModeMutationInUseCacheError,
createDraftModeMutationInUnstableCacheError,
} from '../use-cache/use-cache-messages'
import { ReflectAdapter } from '../web/spec-extension/adapters/reflect'
import { applyOwnerStack } from '../dynamic-rendering-utils'

Expand Down Expand Up @@ -203,17 +207,19 @@ function trackDynamicDraftMode(expression: string, constructorOpt: Function) {
switch (workUnitStore.type) {
case 'cache':
case 'private-cache': {
const error = new Error(
`Route ${workStore.route} used "${expression}" inside "use cache". The enabled status of \`draftMode()\` can be read in caches but you must not enable or disable \`draftMode()\` inside a cache. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
const error = createDraftModeMutationInUseCacheError(
workStore.route,
expression
)
Error.captureStackTrace(error, constructorOpt)
applyOwnerStack(error)
workStore.invalidDynamicUsageError ??= error
throw error
}
case 'unstable-cache':
throw new Error(
`Route ${workStore.route} used "${expression}" inside a function cached with \`unstable_cache()\`. The enabled status of \`draftMode()\` can be read in caches but you must not enable or disable \`draftMode()\` inside a cache. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
throw createDraftModeMutationInUnstableCacheError(
workStore.route,
expression
)

case 'prerender':
Expand Down
12 changes: 6 additions & 6 deletions packages/next/src/server/request/headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import { isRequestAPICallableInsideAfter } from './utils'
import { applyOwnerStack } from '../dynamic-rendering-utils'
import { InvariantError } from '../../shared/lib/invariant-error'
import { RenderStage } from '../app-render/staged-rendering'
import {
createHeadersInUseCacheError,
createHeadersInUnstableCacheError,
} from '../use-cache/use-cache-messages'

/**
* This function allows you to read the HTTP incoming request headers in
Expand Down Expand Up @@ -65,18 +69,14 @@ export function headers(): Promise<ReadonlyHeaders> {
if (workUnitStore) {
switch (workUnitStore.type) {
case 'cache': {
const error = new Error(
`Route ${workStore.route} used \`headers()\` inside "use cache". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`headers()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
)
const error = createHeadersInUseCacheError(workStore.route)
Error.captureStackTrace(error, headers)
applyOwnerStack(error)
workStore.invalidDynamicUsageError ??= error
throw error
}
case 'unstable-cache':
throw new Error(
`Route ${workStore.route} used \`headers()\` inside a function cached with \`unstable_cache()\`. Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use \`headers()\` outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
)
throw createHeadersInUnstableCacheError(workStore.route)
case 'generate-static-params':
throw new Error(
`Route ${workStore.route} used \`headers()\` inside \`generateStaticParams\`. This is not supported because \`generateStaticParams\` runs at build time without an HTTP request. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context`
Expand Down
5 changes: 2 additions & 3 deletions packages/next/src/server/request/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StaticGenBailoutError } from '../../client/components/static-generation-bailout'
import { afterTaskAsyncStorage } from '../app-render/after-task-async-storage.external'
import type { WorkStore } from '../app-render/work-async-storage.external'
import { createSearchParamsInUseCacheError } from '../use-cache/use-cache-messages'

export function throwWithStaticGenerationBailoutErrorWithDynamicError(
route: string,
Expand All @@ -15,9 +16,7 @@ export function throwForSearchParamsAccessInUseCache(
workStore: WorkStore,
constructorOpt: Function
): never {
const error = new Error(
`Route ${workStore.route} used \`searchParams\` inside "use cache". Accessing dynamic request data inside a cache scope is not supported. If you need some search params inside a cached function await \`searchParams\` outside of the cached function and pass only the required search params as arguments to the cached function. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
)
const error = createSearchParamsInUseCacheError(workStore.route)

Error.captureStackTrace(error, constructorOpt)
workStore.invalidDynamicUsageError ??= error
Expand Down
13 changes: 8 additions & 5 deletions packages/next/src/server/route-modules/app-route/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ import { executeRevalidates } from '../../revalidation-utils'
import { trackPendingModules } from '../../app-render/module-loading/track-module-loading.external'
import { InvariantError } from '../../../shared/lib/invariant-error'
import { createPrerenderResumeDataCache } from '../../resume-data-cache/resume-data-cache'
import {
createRouteHandlerRequestInUseCacheError,
createRouteHandlerRequestInUnstableCacheError,
} from '../../use-cache/use-cache-messages'

export class WrappedNextRouterError {
constructor(
Expand Down Expand Up @@ -1324,12 +1328,11 @@ function trackDynamic(
case 'private-cache':
// TODO: Should we allow reading cookies and search params from the
// request for private caches in route handlers?
throw new Error(
`Route ${store.route} used "${expression}" inside "use cache". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use "${expression}" outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`
)
throw createRouteHandlerRequestInUseCacheError(store.route, expression)
case 'unstable-cache':
throw new Error(
`Route ${store.route} used "${expression}" inside a function cached with "unstable_cache(...)". Accessing Dynamic data sources inside a cache scope is not supported. If you need this data inside a cached function use "${expression}" outside of the cached function and pass the required dynamic data in as an argument. See more info here: https://nextjs.org/docs/app/api-reference/functions/unstable_cache`
throw createRouteHandlerRequestInUnstableCacheError(
store.route,
expression
)
case 'prerender':
const error = new Error(
Expand Down
5 changes: 2 additions & 3 deletions packages/next/src/server/use-cache/cache-life.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { InvariantError } from '../../shared/lib/invariant-error'
import { workAsyncStorage } from '../app-render/work-async-storage.external'
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external'
import { createCacheLifeOutsideUseCacheError } from './use-cache-messages'

export type CacheLife = {
// How long the client can cache a value without checking with the server.
Expand Down Expand Up @@ -94,9 +95,7 @@ export function cacheLife(profile: CacheLifeProfiles | CacheLife): void {
case 'unstable-cache':
case 'generate-static-params':
case undefined:
throw new Error(
'`cacheLife()` can only be called inside a "use cache" function.'
)
throw createCacheLifeOutsideUseCacheError()
case 'cache':
case 'private-cache':
break
Expand Down
5 changes: 2 additions & 3 deletions packages/next/src/server/use-cache/cache-tag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external'
import { validateTags } from '../lib/patch-fetch'
import { createCacheTagOutsideUseCacheError } from './use-cache-messages'

export function cacheTag(...tags: string[]): void {
if (!process.env.__NEXT_USE_CACHE) {
Expand All @@ -21,9 +22,7 @@ export function cacheTag(...tags: string[]): void {
case 'unstable-cache':
case 'generate-static-params':
case undefined:
throw new Error(
'`cacheTag()` can only be called inside a "use cache" function.'
)
throw createCacheTagOutsideUseCacheError()
case 'cache':
case 'private-cache':
break
Expand Down
Loading
Loading