Tailwind upgrade: Could not load the configuration file
Reproduced on Windows 11 with a virtual drive: the exact failing version, why @next still breaks today, and the command that migrates a v3 project cleanly.
TL;DR#
On Windows, npx @tailwindcss/upgrade up to 4.0.0 fails with Could not load the configuration file: Can't resolve '././E:\…\tailwind.config.js' when your project lives on a different drive from the npm cache. Tailwind fixed it in PR #15927, released in 4.0.1. Do not pin @next: on npm that tag still points at an early 4.0 tool, which now crashes for a different reason. Run the untagged command:
npx @tailwindcss/upgradeThe error#
The Stack Overflow question shows a Vite + React project on Tailwind v3 where npx @tailwindcss/upgrade@next --force stopped at the configuration step. The bug report it links, issue #15220, has the full line: the project was on E:, the npm cache on C:.
The same failure, reproduced on Windows 11 with Node 26.7.0, a Tailwind 3.4.19 project on a subst drive Q: and the npm cache on C::
$ cd /q/run1 && NO_COLOR=1 npx -y @tailwindcss/upgrade@4.0.0 --force
≈ tailwindcss v4.0.0
│ Searching for CSS files in the current directory and its subdirectories…
│ ↳ Linked `.\tailwind.config.js` to `.\src\index.css`
│ Migrating JavaScript configuration files…
│ ↳ Could not load the configuration file: Can't resolve '././Q:\run1\tailwind.config.js' in 'C:\Users\mahdi\AppData\Local\npm-cache\_npx\cdd4d330f43063a9\node_modules\@tailwindcss\upgrade\dist'
exit code: 1Two details give the cause away: the doubled ././ in front of a full Windows path, and the folder it searched, which is the upgrade tool's own dist folder inside the npx cache, not your project.
Why the path breaks across drives#
To read your v3 config, the tool compiles a small stylesheet containing an @config directive that points at your tailwind.config.js. In 4.0.0, prepare-config.ts builds that path with Node's path.relative() from __dirname, the tool's own install folder, to your config file, adds ./ when the result does not start with a dot, then writes it into a template that starts with another ./.
On a single drive that works, because path.relative() returns something like ..\..\project\tailwind.config.js. Between two drive letters no relative path exists, so Node returns the target's absolute path. The PR description quoted in the accepted answer puts it this way: "The issue on Windows specifically is that file.relative(…) can also return a legit absolute path, e.g. when the file is on a different drive." The tool still prefixed it, and the resolver looked for a file literally named ././Q:\run1\tailwind.config.js inside its own dist folder. A comment in the source gives the reason for starting there: "This is required so that the base for Tailwind CSS can bet inside the @tailwindcss-upgrade package and we can require tailwindcss properly."
The same steps can be replayed on any operating system with Node's Windows path rules. This script copies the 4.0.0 logic:
// Same steps as prepare-config.ts in @tailwindcss/upgrade 4.0.0, with Windows path rules
const path = require('node:path').win32
const dist = String.raw`C:\Users\dev\AppData\Local\npm-cache\_npx\0044b4041b3b52e1\node_modules\@tailwindcss\upgrade\dist`
for (const file of [String.raw`Q:\project\tailwind.config.js`, String.raw`C:\project\tailwind.config.js`]) {
let relative = path.relative(dist, file)
console.log(`relative: ${relative} isAbsolute: ${path.isAbsolute(relative)}`)
if (!relative.startsWith('.')) relative = './' + relative
console.log(`@config './${relative}';`)
}Saved as relative.cjs and run with node, it prints the broken path for the second drive and a working one for the same drive:
relative: Q:\project\tailwind.config.js isAbsolute: true
@config '././Q:\project\tailwind.config.js';
relative: ..\..\..\..\..\..\..\..\..\..\..\project\tailwind.config.js isAbsolute: false
@config './..\..\..\..\..\..\..\..\..\..\..\project\tailwind.config.js';The fix commit skips the ./ prefix when the path is absolute (a path.isAbsolute check), both in prepare-config.ts and in the stylesheet-linking step of migrate.ts, and it drops the hard-coded ./ from the @config template. It was merged on 28 January 2025 and is listed under 4.0.1 in the changelog as "Ensure JavaScript config files on different drives are correctly migrated". The GitHub compare API places the merge commit after the v4.0.0 tag and inside v4.0.1.
Nothing in your project causes this, so editing tailwind.config.js or the CSS file will not help. The reproduction's negative control confirms it: the same 4.0.0 tool on the same project, copied to C:, did not raise the Can't resolve error. It stopped later on an unrelated error, explained in the next section.
Fix: run the current upgrade tool#
- Commit or stash your work first. The current tool stops with "Git directory is not clean" when there are uncommitted changes, unless you pass
--force(see index.ts). The upgrade guide also recommends a new branch and Node.js 20 or higher.
git switch -c tailwind-v4- Run the tool without a version tag, from the project root, on whatever drive it is on:
npx @tailwindcss/upgradeThat is the command printed in the upgrade guide. Running the tool from WSL, the workaround in the accepted answer, is no longer needed. Moving the project to C: does not rescue an old pinned version either: on C:, 4.0.0 got past the path bug and then hit the crash described next.
Why @next still fails today#
The question uses the next tag. On 6 November 2026 the npm registry lists next as 4.0.6, published on 10 February 2025, and latest as 4.3.5. Version 4.0.6 contains the drive fix, but it crashes one step later:
$ cd /q/run-next && NO_COLOR=1 npx -y @tailwindcss/upgrade@next --force
≈ tailwindcss v4.0.6
│ Searching for CSS files in the current directory and its subdirectories…
│ ↳ Linked `.\tailwind.config.js` to `.\src\index.css`
│ Migrating JavaScript configuration files…
Error: Missing field `negated` on ScannerOptions.sources
at Ml (file:///C:/Users/mahdi/AppData/Local/npm-cache/_npx/0044b4041b3b52e1/node_modules/@tailwindcss/upgrade/dist/index.mjs:227:24)
at jl (file:///C:/Users/mahdi/AppData/Local/npm-cache/_npx/0044b4041b3b52e1/node_modules/@tailwindcss/upgrade/dist/index.mjs:226:153)
at Gi (file:///C:/Users/mahdi/AppData/Local/npm-cache/_npx/0044b4041b3b52e1/node_modules/@tailwindcss/upgrade/dist/index.mjs:210:1259)
at async ca (file:///C:/Users/mahdi/AppData/Local/npm-cache/_npx/0044b4041b3b52e1/node_modules/@tailwindcss/upgrade/dist/index.mjs:229:5368) {
code: 'InvalidArg'
}
exit code: 1The registry manifest of 4.0.6 declares its two companion packages, the native @tailwindcss/oxide and @tailwindcss/node, with caret ranges (^4.0.6), so npx installs today's 4.3.5 of both next to the old tool. The reproduction found 4.3.5 of both in the npx installs of 4.0.0, 4.0.1 and 4.0.6, and all three crashed with this error. Changing only that pairing fixes it: the same 4.0.6 tool, run with both companions pinned to 4.0.6, migrated the project and exited with code 0.
This is a known break. Issue #17500 reports the same Missing field error from @tailwindcss/postcss 4.0.0 picking up a newer @tailwindcss/node. A maintainer answered that it was fixed in 4.0.7, and the 4.0.7 changelog lists "Pin exact version of tailwindcss in @tailwindcss/* packages". To someone who hit the error through a @next command, the maintainer replied: "use @latest instead of @next to get the latest version."
On Q:, 4.0.1 no longer raised the Can't resolve error, which confirms the drive fix shipped there, but none of the early 4.0 tools can finish an upgrade any more. Read the first line the tool prints, ≈ tailwindcss v…, to see which version actually ran.
Verify the migration#
On the Q: drive that broke 4.0.0, the untagged command ran 4.3.5 and completed:
$ cd /q/run-latest && NO_COLOR=1 npx -y @tailwindcss/upgrade --force
≈ tailwindcss v4.3.5
│ ↳ Upgrading from Tailwind CSS `v3.4.19`
│ Searching for CSS files in the current directory and its subdirectories…
│ ↳ Linked `.\tailwind.config.js` to `.\src\index.css`
│ Migrating JavaScript configuration files…
│ ↳ Migrated configuration file: `.\tailwind.config.js`
│ Migrating stylesheets…
│ ↳ Migrated stylesheet: `.\src\index.css`
│ Updating dependencies…
│ ↳ Updated package: `tailwindcss`
│ Migrating templates…
│ ↳ Migrated templates for configuration file: `.\tailwind.config.js` (0 files changed)
│ ↳ No PostCSS config found, skipping migration.
fatal: not a git repository (or any of the parent directories): .git
│ No changes were made to your repository.
exit code: 0Check three things after the run:
- the stylesheet now starts with
@import 'tailwindcss';, and your theme extensions have become CSS variables in an@themeblock (here--color-brand: #1d4ed8;); tailwind.config.jsis gone when everything in it could be moved to CSS;package.jsonliststailwindcss4.x.
The test project also printed "fatal: not a git repository", because it was not a Git repository. Inside a repository, run git diff and read the changes before committing.
When the tool succeeds but the build does not#
The test project had no PostCSS config, and the tool printed "No PostCSS config found, skipping migration". A real Vite project usually has one. If the dev server then fails with "It looks like you're trying to use tailwindcss directly as a PostCSS plugin", your PostCSS config still loads the v3 plugin: the PostCSS plugin fix explains it, and the upgrade guide recommends the @tailwindcss/vite plugin for Vite instead. If adding that plugin fails with Failed to resolve "@tailwindcss/vite". This package is ESM only, Vite is reading your config as CommonJS: see the ESM-only fix.
If you skip the tool and keep a JavaScript config, remember that v4 does not detect tailwind.config.js on its own. Custom classes such as border-border then fail, as in the border-border fix, which covers the @config path. A v3 safelist is not restored by @config either: Tailwind v4 @source inline() replaces it.
So the asker's project was never at fault, and neither was --force. A Windows path quirk in an early 4.0 release of the tool caused the error, and the next tag still installs one of those early releases. Run the untagged npx @tailwindcss/upgrade and check the version on its first line of output.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
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.
Continue Reading
Fix Tailwind v4 IntelliSense not working in VS Code
Find which layer has stopped working: Tailwind project discovery, document mapping, or automatic suggestions inside JSX strings.
Fix shadcn "No Tailwind CSS configuration found" in Vite
What shadcn init actually looks for before it says Tailwind is missing, reproduced on Tailwind 3 and 4 with the one line that fixes each.
Google Fonts not working in Tailwind + Vite: @import order
Why the font-inter class exists but the text stays in the default face in a React and Vite project, and the one-line move that makes the browser download Inter.


