Skip to content
loke.dev
A glowing modular pathway curves around a cracked dark block on a navy background

Next.js 16 “Module Factory Is Not Available”: Diagnose Turbopack HMR

Identify the Cache Components and lazy-loading Turbopack HMR regression, isolate it with Webpack, and validate production separately.

Published Updated 7 min read

The short answer

If Next.js 16 throws “Module … was instantiated … but the module factory is not available” after you edit a Server Component, first treat it as a development bundler problem - not proof that your data, cache, or production runtime is broken. The clearest known trigger combines Turbopack Hot Module Replacement, Cache Components or a file-leveluse cachedirective, a lazy-loaded client boundary, and a dynamic route. Theopen Next.js issuereproduces that combination and scopes the affected stage tonext dev.

The safest immediate mitigation is to run development with Webpack while leaving the production build unchanged until you've evidence that production is affected:

{
  "scripts": {
    "dev": "next dev",
    "dev:webpack": "next dev --webpack",
    "build": "next build"
  }
}

Next.js documents--webpackas the supported way to use Webpack instead of the default Turbopack bundler in development. This is a supported diagnostic switch, not an undocumented environment variable. See theNext.js CLI reference.

Confirm that you've the same failure

Don't diagnose from the last sentence of the stack trace alone. The same wording can appear when different module graphs fail. The reported Cache Components regression has a more specific fingerprint:

  • The error appears in next dev, commonly after saving a Server Component or repeating Fast Refresh.
  • The stack mentions app-rsc, a client reference proxy, or a lazy-loaded client module.
  • The affected route sits under a layout or component using the use cache directive, with cacheComponents enabled.
  • The tree includes React.lazy or next/dynamic and often a dynamic or catch-all segment.
  • A full reload may recover temporarily, but the next source edit can recreate the failure.

The upstream reproduction says removinguse cache, using Webpack, or removing the lazy-loaded component stops the failure. It also reports that replacingReact.lazywithnext/dynamicdoesn't help. Those observations come from theissue’s minimal reproduction. test them against your own tree rather than assuming every “module factory” error has this cause.

A recentNext.js community reportand a separatePayload CMS community reportshow the same error shape during a Next.js 16 Cache Components migration. These threads establish current developer pain. they are not the source of the technical diagnosis.

Use a two-run test to isolate Turbopack

Run the same edit sequence twice from a cleanly restarted development server:

  1. Start your normal next dev command, open the affected route, and save the same Server Component several times.
  2. Stop that server and run npm run dev:webpack (or the equivalent command for your package manager).
  3. Repeat the same edits and navigation path.

If the error is repeatable under Turbopack but not Webpack, you've isolated the bundler/HMR path without changing application behavior. Keep the alternate script while you investigate. If both bundlers fail on the initial page load, stop using this guide as the diagnosis: inspect the first application error, server log, import boundary, and dependency compatibility instead.

Don't make “delete every cache” your permanent fix. Restarting the server or removing generated output may clear a stale development graph, but recurrence after the next edit is evidence that the trigger remains.

Why this combination is suspicious

Next.js 16 made Turbopack the default bundler and introduced Cache Components as an opt-in caching model. TheNext.js 16 announcementdescribes both changes. WithcacheComponents: true, theuse cache documentationallows a file, component, or function to become cacheable.

The upstream issue shows that the failure occurs while Turbopack updates the development module graph around a cached layout and a lazy client boundary. That's the supported conclusion. It's reasonable to infer that HMR retained an invalid relationship between module instances and factories, but the issue doesn't yet identify a merged root-cause fix. Don't present that inference as settled framework internals.

Mitigation 1: use Webpack for development

This is the lowest-risk option when you need to keep both Cache Components and lazy loading. It changes the development bundler, not the route’s caching contract.

{
  "scripts": {
    "dev": "next dev",
    "dev:webpack": "next dev --webpack"
  }
}

Use the Webpack script only for affected work if the rest of the team benefits from Turbopack. Record the exact Next.js version and link the upstream issue in the temporary workaround so that somebody can remove it deliberately later.

Mitigation 2: narrow the cache boundary

A file-leveluse cacheon a layout makes every exported async function in that file part of the cached scope. If the layout also owns a lazy client boundary, move the cache directive closer to the data read when that still matches the product’s freshness rules.

The next is anillustrative refactor. Replace the query and lifetime with values that match your application:

import { cacheLife } from 'next/cache'
import NavigationClient from './NavigationClient'

async function getNavigation() {
  'use cache'
  cacheLife('hours')

  return db.navigation.findMany({
    orderBy: { position: 'asc' },
  })
}

export default async function Layout({
  children,
}: {
  children: React.ReactNode
}) {
  const items = await getNavigation()

  return (
    <>
      <NavigationClient items={items} />
      {children}
    </>
  )
}

This refactor is appropriate only if the navigation result is safe to share and may be stale for the chosen lifetime. Theexisting loke.dev Cache Components guideexplains how to choose sharing, lifetime, and invalidation rules. Don't move user-specific data into a shared cache merely to avoid a development error.

Mitigation 3: remove the lazy boundary temporarily

If the component is small or already needed on the initial route, a static import can be a reasonable temporary trade. The upstream reproduction reports that removing the lazy-loaded component avoids its failure:

// Temporary diagnostic: replace a lazy boundary with a static import.
import DynamicPanel from './DynamicPanel'

export default async function Layout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <>
      <DynamicPanel />
      {children}
    </>
  )
}

Measure the resulting client bundle and loading behavior before keeping this change. A workaround that removes code splitting can shift cost from development reliability to every visitor.

Don't confuse an HMR regression with a production failure

The reported Next.js issue marks the affected stage as local development and reproduces the problem after source edits. That evidence doesn't establish a production build or runtime failure. Keep the checks separate:

  • Run next build with the same configuration used in deployment.
  • Start the production server or preview artifact and load the affected dynamic routes directly.
  • Navigate between routes that cross the lazy boundary.
  • Exercise cached reads and invalidation separately from module loading.
  • Check browser and server logs from the first request, not only after a development hot update.

If production also fails, capture a minimal reproduction for that path. Don't cite the development-only issue as proof of the production cause.

A compact decision table

Error only after saves. Webpack development is stable: keep your application code, usenext dev --webpack, and watch the upstream issue.

Error disappears when a broaduse cacheis narrowed: keep the narrower boundary only if its sharing and freshness contract is correct.

Error disappears with a static import: decide whether the lost code splitting is acceptable. otherwise prefer the Webpack development script.

Error occurs on the first load under both bundlers: investigate imports, client/server boundaries, and dependency versions. this specific HMR regression is not yet isolated.

Error occurs in a production artifact: create a production reproduction and treat it as a separate incident.

When can you remove the workaround?

As of August 3, 2026, the upstream issue is open and shows no linked pull request or milestone. Before returning to Turbopack development, check that issue and the release notes for your target Next.js version. Then rerun the exact edit sequence that originally failed. an upgrade alone is not a verification.

Leave a short comment beside the alternate script with the issue URL, the affected route, and the test that proves the workaround is no longer needed. That turns a mysterious permanent flag into a reversible engineering decision.

Sources

Primary technical sources:Next.js issue #85538.Next.js CLI reference.Cache Components configuration.use cache directive. and theNext.js 16 release announcement.

Demand evidence only: recent reports in theNext.jsandPayload CMScommunities.