If you’ve ever deployed a Tailwind project to Cloudflare Pages and gotten slapped with a cryptic npm error, trust me—you’re not alone. I ran into the same error over and over until I finally dug deep enough to understand what was actually going on.
Here’s the story, the cause, and the fix (that Cloudflare Pages actually accepts).
🚨 The Error That Would Not Die
Every deployment failed with this lovely message:
npm error `npm ci` can only install packages when your package.json and
package-lock.json are in sync.
npm error Invalid: lock file's picomatch@2.3.1 does not satisfy picomatch@4.0.3
npm error Missing: picomatch@2.3.1 from lock file
This is npm’s way of saying “your dependency tree is a mess and I want nothing to do with it.”
The frustrating part? Everything ran locally just fine. Only Cloudflare Pages blew up because it uses npm ci, which has zero tolerance for dependency inconsistencies.
🕵 The Root Cause (a surprisingly tangled chain)
Once I started peeling back the layers, here's what I found:
-
eslint-config-next@15.3.1depends on →eslint-import-resolver-typescript→tinyglobby→fdir@6.5.0 -
fdirexpectspicomatchversion ^3 or ^4 - Meanwhile, other packages in the tree—Tailwind, chokidar, and friends—expect picomatch ^2.x
- npm tried to “helpfully” dedupe everything to picomatch@2.3.1, but that violates
fdir’s peer dependency requirements. - Result: an invalid dependency tree, and
npm cirefuses to install it.
Locally, npm is forgiving. Cloudflare Pages is not.
✅ The Fix (finally something that works)
After trying all sorts of workarounds, the cleanest and most reliable fix was:
➡ Force the entire project to use picomatch v4.
Here’s how.
1. Add picomatch v4 explicitly
In your package.json, add:
"devDependencies": {
"@eslint/eslintrc": "^3",
"picomatch": "^4.0.3",
...
}
2. Add an override so everyone uses v4
{
"overrides": {
"picomatch": "^4.0.3"
}
}
This forces all packages—Tailwind, chokidar, fdir, etc.—to align on v4.
3. Regenerate the lockfile
rm -rf node_modules package-lock.json
npm install
4. Test it
rm -rf node_modules
npm ci
If everything installs cleanly here, Cloudflare Pages will be happy too.
5. Commit & push
git add package.json package-lock.json
git commit -m "Fix picomatch dependency conflicts for Cloudflare Pages"
git push
💡 Why This Works
-
picomatch@4is actually backward-compatible with the^2.xrange most packages want. - The override ensures there's no version split or accidental deduping.
-
fdiris finally satisfied because it requires^3 || ^4. -
npm cinow has a perfectly consistent lock file to work from.
It’s one of those rare dependency battles where the nuclear option (forcing a version everywhere) is actually safe.
🧭 Alternative Workarounds (if you can’t or don’t want to override)
If overrides cause issues in your environment, you could:
- Use
npm install --legacy-peer-deps➝ But Cloudflare Pages doesn’t support custom npm flags - Switch to pnpm or Yarn ➝ They have smarter, less rigid resolution algorithms
- Wait for upstream packages to fix their dependency ranges ➝ Could be whenever… or never
🎉 Wrap-Up
This dependency conflict was one of those rare cases where:
- nothing was technically “broken,”
- but everything was just incompatible enough to make Cloudflare reject the build.
By standardizing on picomatch v4, the entire tree becomes consistent, and Cloudflare Pages finally chills out.
If you'd like, I can also turn this into:
- a shorter knowledge-base-style answer,
- a troubleshooting checklist,
- or a reusable snippet for tech docs.
Top comments (0)