Why only next dev breaks CSS: it was NODE_ENV=production
In Next.js, next build can succeed while next dev alone fails on CSS.
When this happens, it is tempting to suspect your globals.css syntax, PostCSS, Turbopack, or webpack config. But the cause is not always CSS. In this case it was NODE_ENV=production inherited from the parent process.
The symptoms
The symptoms seen during local development were:
npm run buildsucceeds- only
npm run devfails - ordinary CSS in
globals.cssthrowsModule parse failed: Unexpected token - the error points near a valid CSS selector such as
*,
Typically it looks like this:
Module parse failed: Unexpected token (2:0)
Looking at this error alone, it seems like the CSS loader or PostCSS config is broken. But if next build passes, it is safer not to assume the CSS syntax itself is wrong.
What I suspected first
There are several natural suspects:
- a syntax mistake in
globals.css - a missing or malformed
postcss.config.js - Tailwind CSS or CSS Modules configuration
- Next.js webpack/Turbopack switching
- a corrupted cache or
.next/directory
These are worth checking. But when next build passes and only next dev fails, as here, it is often faster to check environment variables before config files.
The real cause was NODE_ENV=production
The cause was that NODE_ENV=production was left in the shell or user environment.
next dev starts the development server, but a child process inherits the parent process's environment variables. So if the calling environment has NODE_ENV=production, production-oriented behavior leaks into what you intended as a development command.
In that state, CSS-processing initialization and dependency handling drift from what you expect, and the result can look like "valid CSS being parsed as JavaScript".
The Next.js documentation also explains that NODE_ENV is a value treated specially across the React ecosystem, and that unexpected or mixed values are worth checking.
Reference: Next.js: Non-Standard NODE_ENV
It affects npm install too
The impact of NODE_ENV=production is not limited to next dev.
The npm documentation explains that when NODE_ENV is production, the default for omit includes dev. In other words, even when you run a normal npm install locally, devDependencies may physically not be installed into node_modules.
Reference: npm-install: omit / include
In that state, secondary failures appear:
cross-envis not found- development packages such as TypeScript or ESLint are not found
- a package you thought you installed with
npm install --save-dev <package>cannot be resolved at runtime - build or dev-server failures look like dependency mistakes
If a CSS error and missing devDependencies appear around the same time, you can suspect NODE_ENV pollution fairly strongly.
Checking in PowerShell
On Windows PowerShell, first check the current session value:
$env:NODE_ENV
If nothing is printed, it is not set directly in the current PowerShell session.
Next, check the user and machine environment variables:
[Environment]::GetEnvironmentVariable("NODE_ENV", "User")
[Environment]::GetEnvironmentVariable("NODE_ENV", "Machine")
If production appears here, it may be inherited by child processes even after you reopen the terminal.
For a quick, temporary check, run with the development mode made explicit:
$env:NODE_ENV = "development"
npm run dev
But this only affects that one PowerShell session. For a durable fix, it is more stable to make it explicit in your scripts.
Fixing it in package.json
To avoid depending on the local environment, make NODE_ENV explicit in your package.json scripts.
If you want the same syntax on Windows, macOS, and Linux, use cross-env. It is a package that absorbs the per-OS differences in how environment variables are specified.
Reference: cross-env README
Example:
{
"scripts": {
"dev": "cross-env NODE_ENV=development next dev",
"build": "cross-env NODE_ENV=production next build",
"start": "cross-env NODE_ENV=production next start"
}
}
If devDependencies might be missing, reinstall them explicitly:
npm install --include=dev
If cross-env itself is not installed, install with devDependencies first:
npm install --include=dev
npm install --save-dev cross-env
Isolate it before touching CSS or PostCSS
The same Module parse failed can have several causes. Isolating in this order reduces detours.
1. Compare build and dev
npm run build
npm run dev
If only build passes, suspect "dev-server-specific state" rather than a CSS syntax mistake.
2. Check NODE_ENV
$env:NODE_ENV
[Environment]::GetEnvironmentVariable("NODE_ENV", "User")
[Environment]::GetEnvironmentVariable("NODE_ENV", "Machine")
If production appears anywhere, fix that first.
3. Check whether dependencies are installed
npm ls cross-env
npm ls typescript
If devDependencies are missing, reinstall with npm install --include=dev.
4. Only then look at CSS config
If it still fails after all that, look at PostCSS, Tailwind CSS, Next.js config, and the .next/ cache.
This order avoids the accident of forcing config changes to fix "an environment-variable problem that looks like a CSS error".
Why this problem is hard to find
What makes this nasty is that the error message never mentions NODE_ENV=production.
On screen it looks like a CSS parse error. On the npm side, the reason devDependencies are missing is not loudly warned every time. As a result, misdiagnosis is easy:
- assuming it is a Turbopack problem
- rewriting
postcss.config.jsover and over - doubting how
globals.cssis written - only checking whether deleting
.next/fixed it - treating the package install failure as a separate problem
But if the parent environment's NODE_ENV is production, these may all be symptoms from the same root.
Prevention checklist
- make
NODE_ENV=developmentexplicit in thedevscript - make
NODE_ENV=productionexplicit inbuild/start - on Windows, also check
User/Machinescope environment variables - when devDependencies look suspect during
npm install, use--include=dev - even for a CSS parse error, check environment variables first if
next buildpasses
Summary
When only next dev fails on CSS, you want to fix CSS or PostCSS.
But if next build passes, the problem may be the dev server's execution environment rather than the file contents. In particular, when NODE_ENV=production is inherited from the parent process, the behavior of next dev and npm install quietly changes.
Start by checking these three:
$env:NODE_ENV
[Environment]::GetEnvironmentVariable("NODE_ENV", "User")
[Environment]::GetEnvironmentVariable("NODE_ENV", "Machine")
If production appears, fix the environment variable before touching CSS.
Related article: 5 Pitfalls of Next.js output: export and How to Avoid Them