vercel/next.js · error · Error
hmrRefresh can only be used in development mode. Please use
Error message
hmrRefresh can only be used in development mode. Please use refresh instead.
What it means
`router.hmrRefresh()` is a development-only method that triggers Hot Module Replacement for the current route. It throws unconditionally when `process.env.NODE_ENV !== 'development'` because HMR infrastructure does not exist in production builds. The error message directs you to use `router.refresh()` instead, which works in all environments.
Source
Thrown at packages/next/src/client/components/app-router-instance.ts:486
options?.scroll === false
? ScrollBehavior.NoScroll
: ScrollBehavior.Default,
null,
options?.transitionTypes,
null
)
})
},
refresh: () => {
startTransition(() => {
dispatchAppRouterAction({
type: ACTION_REFRESH,
})
})
},
hmrRefresh: () => {
if (process.env.NODE_ENV !== 'development') {
throw new Error(
'hmrRefresh can only be used in development mode. Please use refresh instead.'
)
} else {
// Reset the known routes table so that route predictions are cleared
// when routes change during development.
resetKnownRoutes()
let signal: AbortSignal | undefined
if (process.env.__NEXT_SERVER_COMPONENTS_HMR_CANCELLATION) {
// Abort the superseded generation before scheduling the new one, so its
// request is torn down as early as possible. Halting (not rejecting)
// makes the abort safe regardless of order.
activeHmrRefreshController?.abort()
activeHmrRefreshController = new AbortController()
signal = activeHmrRefreshController.signal
}
startTransition(() => {
dispatchAppRouterAction({
type: ACTION_HMR_REFRESH,View on GitHub (pinned to 0ae8c72462)
Solutions
- Use `router.refresh()` instead — it works in all environments.
- Guard the call: `if (process.env.NODE_ENV === 'development') router.hmrRefresh()`.
- Remove the hmrRefresh call from code paths that run in production.
Example fix
// before — throws in production
router.hmrRefresh()
// after — use refresh (works everywhere)
router.refresh()
// or guard the dev-only method:
if (process.env.NODE_ENV === 'development') {
router.hmrRefresh()
} Defensive patterns
Strategy: validation
Validate before calling
function safeHmrRefresh(router: { hmrRefresh: () => void; refresh: () => void }): void {
if (process.env.NODE_ENV === 'development') {
router.hmrRefresh()
} else {
router.refresh()
}
} Type guard
function isDev(): boolean {
return process.env.NODE_ENV === 'development'
} Prevention
- Prefer router.refresh() which works in all environments.
- Guard hmrRefresh() calls with a NODE_ENV check.
- Remove dev-only router calls from code paths shipped to production.
When it happens
Trigger: Calling `router.hmrRefresh()` in code that executes during a production build (`next build`) or production server (`next start`).
Common situations: Dev-only debugging code left in a production code path; a custom dev toolbar or plugin that calls hmrRefresh without environment checks; shared utility code used in both dev and prod.
Related errors
- NEXT_EVAL_TARBALL not set. Run evals via `pnpm eval` from th
- npm install ./next.tgz failed (exit ${exitCode}): ${stderr}
- Failed to find package manager
- Method unavailable on `ReadonlyURLSearchParams`. Read more:
- Next.js has blocked a javascript: URL as a security precauti
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/cd26a8901d1f7ff7.
Report an issue: GitHub.