Next.js

Fix Turbopack Build Errors from a Webpack Config

Find the plugin behind the unexpected webpack hook, choose a compiler deliberately, and verify that the behaviour you need still runs.

Mahdi Ben RhoumaMahdi Ben Rhouma
8 min read

TL;DR#

Next.js uses Turbopack by default, but your exported configuration contains a webpack hook. Choose next build --webpack when that hook supplies required behaviour. If the hook is obsolete, remove it or the wrapper that adds it; otherwise migrate its behaviour to Turbopack. Adding turbopack: {} only acknowledges the choice: it does not make a webpack plugin execute.

The error that stops the build#

The Builder scaffold report shows a generated integration introducing this mismatch. A minimal App Router application reproduced the same guard on Next.js 16.4.4, React 19.3.0 and Node 24.22.2 in the official node:24-slim Docker image on 2 November 2026:

text
ERROR: This build is using Turbopack, with a `webpack` config and no `turbopack` config.

The message can appear even when you never wrote a webpack rule. In the reported Builder setup, a configuration wrapper adds the hook. Next.js checks the resulting configuration, so searching only the object you originally declared can miss it. Keep the first compiler diagnostic from the log; a later worker failure can obscure the useful explanation.

This page addresses the deliberate configuration guard. If compilation starts and then stays on “Compiling”, use the Turbopack compilation troubleshooting page for that different symptom. A deterministic refusal to accept an ambiguous configuration needs a compiler decision before cache investigation is useful.

Why the default and the hook disagree#

The Next.js upgrade instructions explain the default change in Next.js 16. Both development and production use Turbopack unless you select otherwise. The absence of a Turbopack flag in a package script therefore says nothing about whether webpack is running.

The configuration validator source checks whether the raw configuration has a webpack value and a Turbopack value. When the compiler was selected automatically, the former exists and the latter does not, it prints this error and exits. That is why even a hook which simply returns its argument triggers the message. Next.js cannot infer whether the discarded customisation would matter to your application.

A wrapper is just a function returning configuration. It can take an otherwise empty object and return an object with a webpack function. In the published Builder DevTools integration, the hook is added regardless of the enabled option; the option is checked inside the hook before pushing the plugin. Consequently, disabling that integration through its enabled option does not remove the webpack property. This observation concerns the reported package version, not every future Builder release.

Choose the fix according to what the hook does#

SituationChangeBehaviour to check
A required webpack plugin or rule remainsSelect webpack for the relevant commandThe hook and its output still run
An optional wrapper supplies no required featureRemove that wrapper from the exportRoutes and content still work without its feature
The application is moving to TurbopackReimplement supported behaviour, then remove the old hookThe transformed asset or alias still works
A hook is intentionally irrelevant under TurbopackExplicitly select Turbopack or acknowledge its configThe application does not depend on the ignored hook

Do not choose solely by whether the terminal becomes green. A configuration error disappearing and a feature surviving are separate checks. This matters especially for development overlays, generated assets and imports that only appear on less frequently visited routes.

Fix: retain required webpack behaviour#

  1. Inspect the exported config and the wrappers around it. Search next.config.js, next.config.mjs or next.config.ts for the webpack hook and for integration imports. If the file exports a wrapped object, inspect that integration's documented compiler support. Preserve your existing settings while doing this; replacing the entire config can accidentally drop redirects, images or deployment options.

  2. If the feature requires webpack, update the relevant package scripts. The official Turbopack reference documents these compiler flags. Merge this scripts object into the existing package.json:

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

Select both commands when the integration must work in both environments. It is possible to use different compilers for development and production, but that means you must maintain equivalent behaviour where needed. A loader configured only inside the webpack hook cannot be assumed to work in a Turbopack development session.

  1. Run the actual production command:
bash
npm run build

For a one-off diagnosis before editing scripts, run:

bash
npx next build --webpack

The compiler-selection error should disappear. A subsequent plugin exception is a new failure to diagnose, not evidence that the flag was ignored. In particular, the Builder issue also reports a production DevTools exception about a missing TypeScript instance. Selecting webpack makes that plugin eligible to run; it does not repair the plugin's own initialisation. Do not promise that this flag alone fixes that scaffold end to end.

Remove an optional wrapper without removing your configuration#

If you do not need the feature that the wrapper installs, remove its import and export the underlying configuration directly. For example, an application whose complete config is the following has no wrapper left to add a hook:

js
const nextConfig = {
  reactStrictMode: true,
}
 
export default nextConfig

That is a complete next.config.mjs example, not a request to overwrite an existing application's settings. Keep the settings your application uses, remove only the integration you have identified, and leave other wrappers in place if they remain necessary. A CMS SDK and its development tooling can be different dependencies: removing a DevTools configuration wrapper is not the same action as deleting the page code which loads CMS content.

For the Builder-specific path, this removes that optional DevTools integration from Next's build configuration. It does not fix the separate catch-all route or content configuration discussed in the original issue. Check the page you intended to serve, including a content URL rather than only the scaffold homepage.

Why an empty Turbopack object can hide the missing feature#

The following configuration deliberately demonstrates the trap:

js
export default {
  turbopack: {},
  webpack(config) {
    console.log('CUSTOM_WEBPACK_HOOK_RAN')
    return config
  },
}

In the reproduction, the empty Turbopack object allowed the default build to finish, but the marker never appeared. Explicitly selecting Turbopack produced the same result. With the original hook and explicit webpack selection, the build finished and printed the marker. Removing the hook also allowed the default build to finish.

The minimal test used one layout and one static page; it did not install the Builder application or verify its overlay. The marker establishes which hook runs. The separate package source establishes why an integration that installs its feature inside that hook cannot gain that feature merely from an empty object.

Use this acknowledgement only after deciding the hook may be ignored. It is useful when a config intentionally supports both compilers, with equivalent Turbopack settings elsewhere. It is not an automatic migration tool. Likewise, repeatedly clearing the build directory cannot make Turbopack execute a webpack hook.

Migrate the behaviour, not the property name#

The Turbopack configuration reference exposes rules and aliases for supported use cases. Some webpack loaders work through those rules, with restrictions; webpack plugins are a different extension mechanism. Moving a plugins array underneath the Turbopack object is not a supported migration.

For an SVG component transformation, identify the intended result first: an inline React component or a static image import. Then follow the SVG import fixes for Turbopack and webpack, which explain the SVGR setup and the static-image alternative. That target gives the asset-specific configuration rather than treating a disappearing build error as proof that the SVG was transformed correctly.

For a third-party integration, look for explicit Turbopack support from its publisher. If there is no equivalent for the behaviour you need, retaining webpack is a coherent choice. Avoid inventing an alias or loader rule to replace a plugin whose output you have not identified.

Verify the compiler and the application outcome#

Run the package script that CI executes, inspect the compiler banner, and exercise a route which uses the custom behaviour. A webpack hook can run for different compilation targets, so repeated diagnostic markers do not by themselves indicate a duplicate integration. Remove your temporary diagnostic logging after you have identified the path.

In the isolated reproduction, the baseline exited unsuccessfully before compiling the page; changing only the command to select webpack completed the production build and ran the marker hook. The explicit-Turbopack and empty-config controls completed without that marker. This provides a useful acceptance test for your own decision: retaining a hook requires evidence that it executes; removing it requires evidence that the application no longer needs its effects.

If the next error is a missing Suspense boundary around useSearchParams, continue with the production Suspense build fixes. That failure happens during prerendering after compiler selection, so returning to the Turbopack acknowledgement will not resolve it. Keep the selected compiler in the package script, then diagnose the next concrete error from the first relevant log line.

Further reading: Fix Turbopack's Wrong Workspace Root Warning.

Frequently Asked Questions

|

Have more questions? Contact us

Still stuck? Paste your error.

Paste the error message or stack trace — we check it against every fix and tool on the site.

Matching happens in your browser. When you search, a cleaned error signature is sent so we can spot errors we do not cover yet — never the raw text, your IP address or your e-mail. Do not paste passwords or keys. Details

Written by

Mahdi Ben Rhouma
Mahdi Ben Rhouma

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote

One email a month — the latest explained errors

What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.