Fix Cannot find module 'caniuse-lite/dist/unpacker/agents'
Why npm install, npm ls and update-browserslist-db all report a healthy tree while the error stays, and the one reinstall that actually puts the missing files back.
TL;DR#
browserslist loads its browser data with require('caniuse-lite/dist/unpacker/agents'). The error means that file is absent from node_modules. The stubborn case is an incomplete install, where the caniuse-lite folder exists but its dist directory does not: npm install, npm ls and npx update-browserslist-db@latest all accept that folder and leave it alone. npm ci, which removes node_modules before installing from package-lock.json, puts the files back. The popular npm i caniuse-lite only works when it happens to install a different version.
The error#
The question on Stack Overflow comes from npx create-react-app on Node 14.15.3 and npm 6.14. The same message appears in Vue projects, in Next.js and in Vite projects that use the Babel React plugin, because all of them reach browserslist somewhere in the tree. On Node 22 the output contains these lines:
Error: Cannot find module 'caniuse-lite/dist/unpacker/agents'
Require stack:
- /work/app/node_modules/browserslist/index.js
- /work/app/[eval]The first line of the require stack names the package that asked for the file. In a real project it is usually browserslist, reached through @babel/preset-env, autoprefixer or Next.js.
Why it happens#
caniuse-lite is the compressed browser-support dataset behind browserslist. The third line of browserslist's index.js is:
var agents = require('caniuse-lite/dist/unpacker/agents').agentsThat require runs as soon as browserslist is loaded, before any of your config is read. Everything that targets browsers depends on it: @babel/helper-compilation-targets (used by @babel/preset-env) and autoprefixer both list browserslist as a dependency on the npm registry. Next.js ships its own compiled copy: the published next@16.4.0 file dist/compiled/browserslist/index.js contains this module:
946:e=>{"use strict";e.exports=require("caniuse-lite/dist/unpacker/agents")}That compiled copy does not bundle the data: it loads it from node_modules. The next package also lists caniuse-lite as a direct dependency on the npm registry.
So the error is not about your code or your browserslist query. Node found a caniuse-lite folder, or no folder at all, and that folder has no dist/unpacker/agents.js. The caniuse-lite maintainer's answer to a sibling report (caniuse-lite #39, where dist/unpacker/agents.js itself failed to load ../../data/browsers) was that the node_modules folder was broken, and that the fix was to remove it and the npm cache, then install the dependencies again.
How a folder ends up half-extracted is not documented for the original December 2020 case. Two later reports describe the same state. In a Next.js project's fix, the folder held only package.json, LICENSE and README.md. In another case, a sandbox image shipped a pre-built node_modules and the install step was skipped.
Reproduce it, and see what does not fix it#
The state is easy to simulate. The following was run on 10 October 2026 in the official node:22-bookworm Docker image (Node v22.23.3, npm 10.9.9), with browserslist@4.29.3, which pulled caniuse-lite@1.0.30001815:
npm init -y
npm install browserslist@4.29.3
rm -rf node_modules/caniuse-lite/dist
node -e "console.log(require('browserslist')('last 1 Chrome version'))"The require fails with the error above. Then the usual reflexes, one at a time, from that broken tree.
Plain npm install does nothing:
up to date in 418msThe folder still has no dist, and the error stays.
npm ls reports a clean tree and exits with code 0:
`-- browserslist@4.29.3
`-- caniuse-lite@1.0.30001815
npm ls exit: 0npx update-browserslist-db@latest, the command browserslist itself recommends when its data is old, sees a current version and stops there:
Installed version: 1.0.30001815
caniuse-lite is up to dateIt still prints caniuse-lite has been successfully updated, followed by Problem with browser list retrieval. — a sign of the broken folder — yet the folder is untouched and the error stays. All three accepted a folder that still had its package.json and data directory but no dist.
The most-voted answer, npm i caniuse-lite, also printed up to date in 634ms when the broken folder already held the latest release. The error stayed, and caniuse-lite was now written into package.json as a direct dependency.
Fix#
1. Reinstall from the lockfile with npm ci#
From the project root, with package-lock.json present:
npm ciOn the same broken tree, with node_modules left in place, npm ci printed added 8 packages in 2s, dist was back, and browserslist returned [ 'chrome 154' ]. The npm ci documentation explains why it succeeds where npm install does not: when a node_modules folder is already present, npm ci removes it automatically before it starts installing, so every package is extracted again from scratch.
npm ci also never writes to package.json or package-lock.json, so the fix leaves no trace in your diff. In the reproduction run that deleted node_modules first and then ran npm ci, package.json was byte-identical afterwards.
2. No lockfile? Delete node_modules and install#
npm ci refuses to run without package-lock.json. In that case remove the folder yourself, then install:
rm -rf node_modules
npm installOn Windows PowerShell, the first line is Remove-Item -Recurse -Force node_modules.
3. If it comes back: check the npm cache#
The maintainer's reply above also mentions the npm cache. If a fresh install recreates the same incomplete folder, check the cache before reinstalling again:
npm cache verify
npm ciThe npm cache documentation describes verify as checking the cache folder, garbage-collecting unneeded data and verifying the integrity of the cache index and all cached data. This step was not part of the reproduction above, where the cache was healthy.
Verify the fix#
Load browserslist directly from the project root. A healthy tree prints a browser list:
node -e "console.log(require('browserslist')('last 1 Chrome version'))"[ 'chrome 154' ]You can also check that the file the error names now exists:
ls node_modules/caniuse-lite/dist/unpacker/agents.jsThen run the command that failed (npm start, next dev, npm run build). If npm ls caniuse-lite shows several copies, run the node -e check from the folder of the package named in your require stack. Each copy can be broken on its own.
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.
When npm i caniuse-lite seems to work#
The most-voted Stack Overflow answer, with 65 votes, is npm i caniuse-lite. The reproduction shows when that is true. With a lockfile that held the older 1.0.30001813 as a transitive dependency, deleting its dist and running npm i caniuse-lite printed:
changed 1 package in 2snpm moved to 1.0.30001815, extracted a fresh folder, and the error disappeared. The command worked because the version changed, not because of anything specific to caniuse-lite. When the broken copy is already the latest release, the same command prints up to date and repairs nothing.
The third answer pins an old release, npm i caniuse-lite@1.0.30001281. In the reproduction that also cleared the error, but only indirectly. npm installed the old version at the top level and gave browserslist its own fresh copy of 1.0.30001815 in node_modules/browserslist/node_modules. The project keeps a pinned dataset published on 17 November 2021, according to the npm registry, that nothing in it asked for. The second answer, npm update @babel/preset-env, was not reproduced here. Like the first, it can only help if it causes npm to replace the caniuse-lite folder.
None of these is needed when npm ci restores the tree as the lockfile describes it.
The next error#
Switching to npm ci can surface a different failure. If package-lock.json was produced with legacy-peer-deps and no longer matches package.json under your npm settings, npm ci stops with a list of Missing: … from lock file lines. That case is covered step by step in Fix Firebase Functions Deploy: Missing: X from lock file.
Copying a node_modules folder between machines is a related trap. Rollup's native binaries follow the operating system that ran the install, and the same "delete it and run npm ci where it runs" rule applies to Cannot find module @rollup/rollup-win32-x64-msvc. If the "Cannot find module" error instead comes from TypeScript in vite.config.ts (TS2307) rather than from Node at runtime, it is a TypeScript-side problem (a missing package, a stale TS server or the moduleResolution setting), not a half-installed folder. See Cannot find module '@vitejs/plugin-react'.
The caniuse-lite error is a reminder that a dependency folder can exist without being complete, and that npm install and npm ls did not notice the missing files in the reproduction. When a module path inside an installed package goes missing, reinstall the tree from the lockfile with npm ci before reaching for a new dependency.
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.
Continue Reading
Material UI install fails on React 18 or 19 (ERESOLVE): fix
See why npm refuses the old @material-ui packages on a React 18 or 19 project, which packages to install instead, and why --legacy-peer-deps on React 19 only moves the failure to runtime.
Fix react-scripts: Permission denied on npm run build
Find out in two commands whether your react-scripts bin lost its execute bit or lives on a noexec filesystem, then apply the fix that matches, instead of chmod 777 and sudo.
Fix Cannot find module 'dotenv' in Docker Compose (Node)
Reproduced step by step in Compose: why npm install in the Dockerfile is not enough under a bind mount, and why a new package still goes missing after a rebuild.


