← Debugging Guides

阅读中文版本

Node ERR_PACKAGE_PATH_NOT_EXPORTED — Subpath Blocked by exports Map

Fix ERR_PACKAGE_PATH_NOT_EXPORTED and ERR_PACKAGE_PATH_NOT_DEFINED by reading a dependency exports map and importing only the public subpaths it declares.

intermediatedebuggingnodejsmodulespackage-exports

Symptoms

  • Node throws "ERR_PACKAGE_PATH_NOT_EXPORTED: Package subpath ... is not defined by exports"
  • The same import worked before a dependency minor-version bump
  • Bundlers resolve the path while plain Node refuses it

Possible causes

  • The dependency added an exports map that lists allowed subpaths and omits the one you import
  • You import an internal file path such as pkg/dist/foo.js instead of a documented subpath
  • Condition fields (import/require/default) do not cover the resolution mode you use

Diagnosis steps

Print the package exports map

node -e "console.log(JSON.stringify(require('./node_modules/<pkg>/package.json').exports, null, 2))"

Interpretation

The map enumerates exactly which subpaths are importable. If your path is absent, that import is intentionally private.

Reproduce the resolution failure in isolation

node --input-type=module -e "import('<pkg>/dist/foo.js')"

Interpretation

A direct resolution error here confirms an exports restriction rather than a missing install.

List the subpaths the package actually declares

node -e "const e=require('./node_modules/<pkg>/package.json').exports; console.log(Object.keys(e))"

Interpretation

Pick a declared entry such as the package root or a documented feature path.

Root cause

With an exports field present, Node treats every subpath not listed in it as private, regardless of whether the file exists on disk. Importing an internal file path therefore raises ERR_PACKAGE_PATH_NOT_EXPORTED even though the file is physically present.

Fix

Import only the subpaths the exports map declares, or upgrade to a version that exposes the feature you need. If you own the package, add the subpath to exports under the correct conditions instead of reaching into dist.

Risk note

Adding "exports" without a "./*" fallback is a breaking change for consumers importing deep paths; version it as such.

Verify the fix

Rerun the import and confirm it resolves without error. Add a smoke test that imports the public entry so future exports-map edits break the test instead of production.

Symptoms

The error “Node ERR_PACKAGE_PATH_NOT_EXPORTED — Subpath Blocked by exports Map” points at a specific failure mode. This guide documents the symptoms you can observe, the commands that isolate the cause, the root cause, the fix, and the checks that prove the fix works.

Observed symptoms include:

  • Node throws “ERR_PACKAGE_PATH_NOT_EXPORTED: Package subpath … is not defined by exports”
  • The same import worked before a dependency minor-version bump
  • Bundlers resolve the path while plain Node refuses it

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Print the package exports map

node -e "console.log(JSON.stringify(require('./node_modules/<pkg>/package.json').exports, null, 2))"

The map enumerates exactly which subpaths are importable. If your path is absent, that import is intentionally private.

Step 2: Reproduce the resolution failure in isolation

node --input-type=module -e "import('<pkg>/dist/foo.js')"

A direct resolution error here confirms an exports restriction rather than a missing install.

Step 3: List the subpaths the package actually declares

node -e "const e=require('./node_modules/<pkg>/package.json').exports; console.log(Object.keys(e))"

Pick a declared entry such as the package root or a documented feature path.

Likely contributors, in order of frequency:

  • The dependency added an exports map that lists allowed subpaths and omits the one you import
  • You import an internal file path such as pkg/dist/foo.js instead of a documented subpath
  • Condition fields (import/require/default) do not cover the resolution mode you use

Root Cause

With an exports field present, Node treats every subpath not listed in it as private, regardless of whether the file exists on disk. Importing an internal file path therefore raises ERR_PACKAGE_PATH_NOT_EXPORTED even though the file is physically present.

The Fix

Import only the subpaths the exports map declares, or upgrade to a version that exposes the feature you need. If you own the package, add the subpath to exports under the correct conditions instead of reaching into dist.

Watch out: Adding “exports” without a “./*” fallback is a breaking change for consumers importing deep paths; version it as such.

// package.json of the dependency
{
  "exports": {
    ".": { "import": "./dist/index.mjs", "require": "./dist/index.cjs" },
    "./parser": "./dist/parser.mjs"
  }
}

// ✅ import a declared subpath
import { parse } from 'the-pkg/parser';

// ❌ import a private file path (throws ERR_PACKAGE_PATH_NOT_EXPORTED)
// import { parse } from 'the-pkg/dist/parser.mjs';

Verify and Prevent

Rerun the import and confirm it resolves without error. Add a smoke test that imports the public entry so future exports-map edits break the test instead of production.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.