Skip to content
Latchkey

Node ERR_PACKAGE_PATH_NOT_EXPORTED in CI - Fix the Exports Map Subpath

ERR_PACKAGE_PATH_NOT_EXPORTED means a package defines an exports map, and you imported a subpath the map does not expose, so the deep import is blocked.

What this error means

A node import throws Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined or Package subpath ... is not defined by exports, for a deep import into a dependency.

node
node:internal/modules/esm/resolve:282
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/internal'
is not defined by "exports" in
/home/runner/work/app/app/node_modules/some-lib/package.json

Diagnose it: the shell in CI is not your shell

Package scripts run under a different shell, a different PATH, and a non-interactive environment on a runner. Most scripts that fail only in CI are relying on something the login shell gave them locally: a tool on PATH, an environment variable from a dotfile, or a TTY.

Terminal
# what the script can actually see
npm run env | grep -E "^(PATH|NODE_ENV|CI)=" 

# is the binary on PATH for the script, not just for you?
npm exec -- which <tool> || echo "not resolvable from npm scripts"

# run the exact script with tracing
sh -x -c "$(node -p "require('./package.json').scripts.build")"

Common causes

Importing a path the exports map does not list

The package restricts which files are importable via exports, and the deep path you used is not among them.

Relying on an internal file path that became private

A package added an exports map in a new version, locking down internals the code previously reached into.

How to fix it

Import a supported entry point

  1. Check the package exports map for the public subpaths.
  2. Import from a documented entry instead of the internal path.
JavaScript
import { thing } from 'some-lib';
// not: import { thing } from 'some-lib/lib/internal';

Make failures fail the job

A multi-command script can report success while a middle command failed, which produces the worst kind of CI result: a green build that shipped something broken.

.github/workflows/ci.yml
# pipefail is NOT set by default in every runner shell
- name: Build
  shell: bash
  run: |
    set -euo pipefail
    npm run build | tee build.log

How to prevent it

  • Import only documented entry points, avoid reaching into a package internals, and review exports-map changes when upgrading dependencies.

Frequently asked questions

What causes Node ERR_PACKAGE_PATH_NOT_EXPORTED in CI?
There are 2 common causes: importing a path the exports map does not list and relying on an internal file path that became private. The package restricts which files are importable via exports, and the deep path you used is not among them.
How do I fix Node ERR_PACKAGE_PATH_NOT_EXPORTED in CI?
Import a supported entry point. Check the package exports map for the public subpaths.
What does Node ERR_PACKAGE_PATH_NOT_EXPORTED in CI actually mean?
A node import throws Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined or Package subpath ...
How do I stop Node ERR_PACKAGE_PATH_NOT_EXPORTED in CI happening again?
Import only documented entry points, avoid reaching into a package internals, and review exports-map changes when upgrading dependencies.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card