PACKAGE.JSON EXPORTS DRIFT CHECK · RUNS IN YOUR BROWSER

Does your package.json "exports" map point at files that actually exist?

Paste your package.json and a listing of the files you actually publish (npm pack --dry-run, git ls-files, or a plain find . -type f) and see every literal target in the exports map — across every subpath, every condition (import/require/types/...), every fallback array — that doesn't exist. That's the difference between a package that works on the maintainer's own machine and one that throws ERR_PACKAGE_PATH_NOT_EXPORTED or Cannot find module the moment a stranger runs npm install.

Nothing is uploaded. Both text boxes are parsed in this browser and never leave your device. This checks existence, not behaviour: it never runs your code, resolves an import graph, or reads a file's contents.

1. Paste your files

Prefer a CLI, or want this as a pre-publish CI gate?

Same logic, zero dependencies, one file — reads only local files, no network call:

node cli.mjs check                          # ./package.json
node cli.mjs check path/to/package.json
node cli.mjs check --json                    # machine-readable

Get cli.mjs — Node 18+, nothing to install. Run it after your build step and before npm publish — it checks what's on disk right now, so running it before the build has produced anything will read every export as missing. Exits 1 if any literal export target is missing, so it works as the last gate before a publish that would have broken.

What's checked, and what's deliberately skipped

ShapeHandling
A literal path ("./dist/index.js"), at any subpath, any nesting of conditions, any position in a fallback arrayChecked — reported missing if it doesn't exist
A wildcard target ("./features/*")skipped — resolving one needs matching real files against a pattern, out of scope for v0
A bare specifier ("other-package/subpath")skipped — re-exports another package, nothing on disk to check
null (explicitly blocked subpath)Not a file target, ignored entirely — this is intentional, correct package.json

More: why exports maps drift from what actually publishes, and how to wire this into CI · this checker vs. manually checking each target by eye. Already use publint? See how the two compare.

Common questions

Why does a bad exports target only show up after publish?

On the maintainer's own machine the build has usually already run, so the file the exports map names is sitting right there and everything works. The gap is between what's on disk right now and what actually ends up in the published tarball — a rename during a refactor, a build script that changed its output directory, or an npm publish run before the build step finished, and the first person to find out is a stranger running npm install, not the maintainer.

What is ERR_PACKAGE_PATH_NOT_EXPORTED?

Node's own error when code tries to import a subpath that either isn't listed in the package's exports map at all, or is listed but the file it points to isn't there. It replaced Node's older, more forgiving file resolution, so a package.json that shipped exports without checking every target actually exists is exactly the failure mode this tool looks for.

Is this a bundler or a publish tool?

No. It never runs your package, never resolves an import graph, and never reads a file's contents — it only checks whether each literal path the exports map names exists. Wildcard subpaths ("./features/*") and bare-specifier re-exports of another package are listed as not checked, not as passing or failing.

Is my package.json uploaded anywhere?

No. The browser page parses the text you paste entirely in your own browser and never sends it anywhere. The CLI reads only local files — no network call, ever.