{"record":{"id":"08321cf0424d0e4d","repo":"vercel/next.js","slug":"callingexpression-was-called-outside-a-reques","errorCode":null,"errorMessage":"`${callingExpression}` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context","messagePattern":"`(.+?)` was called outside a request scope\\. Read more: https://nextjs\\.org/docs/messages/next-dynamic-api-wrong-context","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/next/src/server/app-render/work-unit-async-storage.external.ts","lineNumber":480,"sourceCode":"    case 'prerender-ppr':\n    case 'prerender-legacy':\n      return true\n    case 'request':\n    case 'prerender-runtime':\n    case 'validation-client':\n    case 'generate-static-params':\n      return false\n    default:\n      return workUnitStore satisfies never\n  }\n}\n\nexport type WorkUnitAsyncStorage = AsyncLocalStorage<WorkUnitStore>\n\nexport { workUnitAsyncStorageInstance as workUnitAsyncStorage }\n\nexport function throwForMissingRequestStore(callingExpression: string): never {\n  throw new Error(\n    `\\`${callingExpression}\\` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context`\n  )\n}\n\nexport function throwInvariantForMissingStore(): never {\n  throw new InvariantError('Expected workUnitAsyncStorage to have a store.')\n}\n\n/**\n * Returns the resume data cache for the given work unit store, regardless of\n * whether it is mutable (`PrerenderResumeDataCache`) or read-only\n * (`RenderResumeDataCache`). Use `resumeDataCache.mutable` to narrow.\n */\nexport function getResumeDataCache(\n  workUnitStore: WorkUnitStore\n): ResumeDataCache | null {\n  switch (workUnitStore.type) {\n    case 'request':","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/app-render/work-unit-async-storage.external.ts#L462-L498","documentation":"throwForMissingRequestStore() is invoked by useDynamicSearchParams (and similar dynamic APIs) when workUnitAsyncStorage.getStore() returns undefined -- meaning the call happened outside any request/prerender scope. Dynamic APIs like useSearchParams, use(), cookies, headers, etc. require a request context to resolve; calling them in module scope, top-level code, or a non-request context throws this.","triggerScenarios":"Code calls a dynamic API (the `callingExpression`, e.g. 'useSearchParams', 'cookies') at module top level, inside generateStaticParams, in a utility function invoked outside a request, or during build module evaluation where no workUnitStore exists. useDynamicSearchParams checks for the store and, finding none, calls throwForMissingRequestStore.","commonSituations":"Calling cookies()/headers()/useSearchParams() in a shared module or outside of a component/route-handler; using dynamic APIs in a context that runs during import; refactor that moved a dynamic call out of a request-scoped component; SSR misuse where the API is called synchronously at module scope.","solutions":["Move the dynamic API call inside a component, route handler, or other request-scoped function so a workUnitStore is active.","Ensure the code runs during a request (Server Component render, route handler, Server Action) rather than at module evaluation time.","If the value is needed broadly, resolve it once within a request scope and pass it down as a prop/argument.","For useSearchParams in Client Components, wrap usage in a Suspense boundary as required."],"exampleFix":"// before\n// const params = useSearchParams() // at module scope -> throws\n\n// after: call inside the component (request scope)\n// export default function Page() {\n//   const params = useSearchParams()\n//   return <p>{params.get('q')}</p>\n// }","handlingStrategy":"validation","validationCode":"// Ensure a request store exists before calling a dynamic API.\nimport { headers } from 'next/headers'\nfunction safeHeaders() {\n  try { return headers() } catch { return new Headers() }\n}\n// Better: only call within a Server Component/route handler scope.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call dynamic APIs only inside components/route handlers/Server Actions.","Never call cookies/headers/searchParams at module top level.","Pass resolved values down rather than re-fetching in non-request scope.","Wrap Client-Component useSearchParams in a Suspense boundary."],"tags":["dynamic-api","request-scope","use-search-params","async-storage"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}