vercel/next.js · error · Error
`after` was called outside a request scope. Read more: https
Error message
`after` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context
What it means
Thrown by the after() entry point when neither workAsyncStorage nor workUnitAsyncStorage has an active store, meaning after() was called outside a Next.js request scope. after() must run within a request lifecycle (route handler, server action, middleware) so it can attach deferred work to that request; calling it elsewhere has no request to defer from.
Source
Thrown at packages/next/src/server/after/after.ts:16
import { workAsyncStorage } from '../app-render/work-async-storage.external'
import { workUnitAsyncStorage } from '../app-render/work-unit-async-storage.external'
export type AfterTask<T = unknown> = Promise<T> | AfterCallback<T>
export type AfterCallback<T = unknown> = () => T | Promise<T>
/**
* This function allows you to schedule callbacks to be executed after the current request finishes.
*/
export function after<T>(task: AfterTask<T>): void {
const workStore = workAsyncStorage.getStore()
const workUnitStore = workUnitAsyncStorage.getStore()
if (!workStore || !workUnitStore) {
// TODO(after): the linked docs page talks about *dynamic* APIs, which after soon won't be anymore
throw new Error(
'`after` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context'
)
}
const { afterContext } = workStore
return afterContext.after(task, workUnitStore)
}
View on GitHub (pinned to 0ae8c72462)
Solutions
- Move the after() call inside a request-scoped function: a route handler, server action, or page render.
- Ensure the file calling after() is only invoked during request handling, not at import/build time.
- For background work outside requests, use a dedicated task queue or cron instead of after().
Example fix
// before - called at module scope
import { after } from 'next/server'
after(() => logVisit()) // throws: outside request scope
// after - called inside a route handler
import { after } from 'next/server'
export async function GET() {
after(() => logVisit())
return Response.json({ ok: true })
} Defensive patterns
Strategy: validation
Validate before calling
// Only call after() from within a request-scoped handler.
// In user code there is no public API to check the store; rely on call-site discipline.
function assertInRequestScope() {
if (process.env.NEXT_BUILD === '1') throw new Error('after() must not be called at build time')
} Try / catch
try {
after(() => log())
} catch (err) {
if (err.message.includes('outside a request scope')) {
// not in a request; defer to a queue
}
} Prevention
- Call after() only inside route handlers, server actions, or page render functions.
- Never call after() at module top-level, in getStaticProps, or in build-time code.
- Keep after() imports confined to request-handling modules.
When it happens
Trigger: Calling after() at module top-level, inside getStaticProps/getStaticPaths, in a utility module imported outside a request, during build time, or in an instrumentation hook. workStore and workUnitStore are both undefined in these contexts.
Common situations: Importing after() into a shared lib and calling it during module initialization or in a non-request function; calling after() inside a generateStaticParams or generateMetadata that runs at build time; using it in a script run via `next/script` or a worker.
Related errors
- `after()`: Argument must be a promise or a function
- `after()` will not work correctly, because `waitUntil` is no
- Invalid ${options.type} header
- Invalid redirect arguments. Please use a single argument URL
- Preview data is limited to 2KB currently, reduce how much da
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/54c004c266632eca.
Report an issue: GitHub.