Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /path/to/package.json when a package.json is either malformed JSON (trailing commas, comments, single quotes) or contains an invalid "exports", "imports", or "type" field. The fastest fixes are: (1) run node -e "require('./package.json')" to surface JSON syntax errors, (2) restructure a mixed-key "exports" object so all conditions are nested under ".", (3) do a clean npm install if the error is inside node_modules.
Exact Error Messages You Will See
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /project/package.json while importing /project/index.js. "name" is not valid JSON.
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /project/node_modules/some-package/package.json while importing /project/index.js. "exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /project/package.json. "exports" must start with "."
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /project/node_modules/semver/package.json. "name" is not valid JSON.
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /project/node_modules/@emotion/babel-plugin/node_modules/stylis/package.json while importing /project/index.js. "exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /project/node_modules/some-package/package.json while importing file:///project/index.js. "name" is not valid JSON.node:internal/modules/package_json_reader:83
const parsed = modulesBinding.readPackageJSON(...)
Full Error Stack Trace
node:internal/modules/esm/resolve:855
throw new ERR_INVALID_PACKAGE_CONFIG(fileURL, base, message);
^
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config
/project/node_modules/some-package/package.json while importing
file:///project/index.js. "exports" cannot contain some keys starting
with '.' and some not. The exports object must either be an object of
package subpath keys or an object of main entry condition name keys only.
at packageExportsResolve (node:internal/modules/esm/resolve:855:13)
at resolveExports (node:internal/modules/cjs/loader:573:36)
at Module._findPath (node:internal/modules/cjs/loader:652:31)
at Module._resolveFilename (node:internal/modules/cjs/loader:1091:27)
at Module._load (node:internal/modules/cjs/loader:942:27)
at Object.<anonymous> (/project/index.js:1:21) {
code: 'ERR_INVALID_PACKAGE_CONFIG'
}
What is ERR_INVALID_PACKAGE_CONFIG?
ERR_INVALID_PACKAGE_CONFIG is thrown by Node.js when it reads a
package.json file and finds either:
- A JSON syntax error — the file is not valid JSON at all.
- A semantically invalid field — the JSON is syntactically valid but a field
like
"exports","imports", or"type"does not meet Node.js's structural requirements.
The error can originate from your project's own package.json, or from a
package.json file deep inside node_modules. Node.js reads every
package.json it encounters on the path from the importer to the target module,
so a corrupted dependency can block your entire application from starting.
See the official Node.js error docs and the Packages documentation for the full specification.
Error Object Properties
| Property | Value | Notes |
|---|---|---|
err.code | 'ERR_INVALID_PACKAGE_CONFIG' | Always this string; use for programmatic detection |
err.message | Includes the full path to the offending package.json | Parse it to find which file to fix |
| Exit code | 1 | Node.js terminates the process immediately |
| Catchable? | No (startup) / Sometimes (dynamic import) | Thrown during module resolution, often before user code runs |
All Causes at a Glance
| Cause | Symptom in error message | Fix |
|---|---|---|
| Trailing comma or comment in JSON | "name" is not valid JSON or SyntaxError in message |
Remove trailing commas and comments; use node -e "require('./package.json')" |
Mixing subpath and condition keys in "exports" |
"exports" cannot contain some keys starting with '.' and some not |
Nest condition keys under "." subpath |
Exports target does not start with ./ |
"exports" must start with "." |
Change target values to relative paths starting with ./ |
Path traversal (..) in exports target |
Invalid package config ... Invalid "exports" target |
Use ./dist/file.js not ../other/file.js |
Invalid "type" value |
Invalid package config ... "type" is not valid |
Set "type" to "module" or "commonjs" only |
Empty or corrupted package.json in node_modules |
expected value at line 1 column 1 |
Delete node_modules and reinstall |
CI-generated package.json with extra syntax |
SyntaxError or is not valid JSON |
Validate generated JSON with npx jsonlint before use |
| Dependency upgraded with broken exports map (e.g. elasticsearch-js, stylis) | Mixed key error in node_modules/<pkg>/package.json |
Update or pin the dependency; use patch-package as stopgap |
| Node.js version stricter than when package was published | Error appears after node upgrade only |
Update the dependency; or pin the old Node.js version temporarily |
Cause 1 – Malformed JSON (trailing commas, comments, single quotes)
JSON does not allow trailing commas, JavaScript-style comments (// or /* */),
or single-quoted strings. These are valid in JavaScript but illegal in JSON. Build scripts and
code generators occasionally produce invalid JSON — CI pipelines are a common source.
// INVALID package.json — three JSON violations
{
"name": "my-app",
"version": "1.0.0", // trailing comma after last key is illegal
"type": "module", /* comments are not valid JSON */
'scripts': { // single-quoted key is illegal
"start": "node index.js",
} // trailing comma inside object is illegal
}
// VALID package.json
{
"name": "my-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node index.js"
}
}
Diagnosing the JSON syntax error
# Option 1: Node.js built-in — prints the offending line and column
node -e "require('./package.json')"
# Option 2: JSON.parse with readable output
node -e "JSON.parse(require('fs').readFileSync('./package.json','utf8'))"
# Option 3: dedicated JSON linter with line numbers and suggestions
npx jsonlint package.json
package.json is generated by a script (e.g. a
CI pipeline that writes environment-specific fields), add a validation step immediately after
generation: node -e "require('./package.json') && console.log('OK')".
A non-zero exit code will fail the pipeline before Node.js ever tries to use the file.
Cause 2 – Mixed subpath and condition keys in "exports"
The "exports" field supports two distinct forms. At any given nesting level, all
keys must be either subpath keys (start with .) or
condition keys (do not start with .) — never a mix of both.
// INVALID — mixing '.' subpath keys with bare condition keys
{
"exports": {
"import": "./dist/esm/index.js", // condition key (no dot prefix)
"require": "./dist/cjs/index.js", // condition key (no dot prefix)
"./utils": "./dist/utils.js" // subpath key (dot prefix)
}
}
// → Error: "exports" cannot contain some keys starting with '.' and some not
// VALID — all conditions nested under the "." subpath key
{
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"default": "./dist/cjs/index.js"
},
"./utils": "./dist/utils.js"
}
}
// ALSO VALID — top-level conditions only (no subpath keys at all)
{
"exports": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"default": "./dist/cjs/index.js"
}
}
This was the cause behind the stylis package (used by Emotion and Next.js with-emotion
examples) and the USWDS v2.11 issue. The fix in both cases was to nest
the condition keys under a "." subpath key.
Cause 3 – Exports target that does not start with ./
Every value (the target path) in the "exports" and "imports" maps
must be a relative path beginning with ./. Absolute file paths, bare package
specifiers, and file:// URLs are rejected.
// INVALID export targets
{
"exports": {
".": "/absolute/path/index.js", // absolute path — invalid
"./helper": "dist/helper.js", // missing leading ./ — invalid
"./other": "file:///app/dist/other.js", // file:// URL — invalid
"./internal": "../sibling/index.js" // path traversal (..) — invalid
}
}
// VALID export targets
{
"exports": {
".": "./dist/index.js",
"./helper": "./dist/helper.js",
"./package.json": "./package.json"
}
}
Cause 4 – Invalid "type" field value
The "type" field controls whether .js files in the package are
treated as CommonJS or ES modules. Node.js only accepts "module" or
"commonjs" (case-sensitive). Any other string — including common typos — triggers
ERR_INVALID_PACKAGE_CONFIG.
// INVALID "type" values
{ "type": "esm" } // invalid
{ "type": "cjs" } // invalid
{ "type": "es6" } // invalid
{ "type": "modules" } // invalid — extra 's'
{ "type": "Module" } // invalid — case sensitive
// VALID "type" values
{ "type": "module" } // treat .js files as ESM
{ "type": "commonjs" } // treat .js files as CJS (also the default if omitted)
Cause 5 – Empty or corrupted package.json in node_modules
A failed or interrupted npm install can leave a package.json file
empty or partially written. Node.js reads these files at module resolution time; an empty file
causes a JSON parse error at line 1, column 1.
Invalid package config /app/node_modules/semver/package.json) after an upgrade
that interrupted the npm install mid-write. The supabase auth-js package triggered the same
issue in Deno's node_modules cache. The fix in all cases was a clean reinstall.
# Clean reinstall — macOS / Linux
rm -rf node_modules
rm -f package-lock.json
npm cache clean --force
npm install
# Clean reinstall — Windows (Command Prompt)
rd /s /q node_modules
del package-lock.json
npm cache clean --force
npm install
# Clean reinstall — Windows (PowerShell)
Remove-Item -Recurse -Force node_modules
Remove-Item package-lock.json
npm cache clean --force
npm install
Cause 6 – Malformed conditional exports (typos in condition names)
Node.js recognizes specific built-in condition names: "import",
"require", "default", "node", "node-addons",
"browser", "development", "production". Typos in these
names do not throw ERR_INVALID_PACKAGE_CONFIG directly but cause no conditions to
match, which can cascade into other errors. However, structurally invalid condition objects — such
as a condition whose value is not a string, object, or array — do trigger it.
// INVALID — condition value is a number, not a path or nested object
{
"exports": {
".": {
"import": 1, // must be a string path or nested object
"require": null // null is only valid to block a subpath, not a condition
}
}
}
// VALID — standard dual CJS/ESM exports with default fallback
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"default": "./dist/index.cjs"
}
}
}
// VALID — nested conditions (Node.js + browser splits)
{
"exports": {
".": {
"node": {
"import": "./dist/node.mjs",
"require": "./dist/node.cjs"
},
"browser": "./dist/browser.js",
"default": "./dist/index.js"
}
}
}
Fix for Dependency-Owned package.json (patch-package)
When the invalid package.json is inside a third-party dependency and no fixed
release is available, use
patch-package
to apply a local fix that survives npm install.
# 1. Manually edit the offending file in node_modules
# e.g. node_modules/some-package/package.json
# 2. Generate the patch file
npx patch-package some-package
# 3. Commit the patches/ directory to source control
# 4. Auto-apply after every install — add to package.json scripts:
# "postinstall": "patch-package"
Fix for Node.js Version Mismatch in CI / Docker
If the error only appears on CI or in a Docker container but not locally, the Node.js version probably differs. Newer versions apply stricter validation.
# Check versions in both environments
node --version
npm --version
# Pin Node.js in a Dockerfile
FROM node:20-alpine
# Pin Node.js in .nvmrc (for nvm / fnm)
echo "20" > .nvmrc
# Pin in GitHub Actions
- uses: actions/setup-node@v4
with:
node-version: '20'
# Diagnose which package triggers the error in Node.js 22+
# The error message contains the full path — grep for it:
node index.js 2>&1 | grep "ERR_INVALID_PACKAGE_CONFIG"
Validating Your Own exports Map
Use this checklist before publishing a package with a non-trivial "exports" field.
// package.json validation checklist
// 1. Every target path starts with ./
// INVALID: "dist/index.js" VALID: "./dist/index.js"
// 2. No path traversal in targets
// INVALID: "../lib/index.js" VALID: "./lib/index.js"
// 3. No mixing subpath and condition keys at the same level
// INVALID:
{
"exports": {
"import": "./esm.js", // condition key
"./helper": "./helper.js" // subpath key — MIXED!
}
}
// VALID:
{
"exports": {
".": { "import": "./esm.js" },
"./helper": "./helper.js"
}
}
// 4. "default" is the last condition key in every conditions object
{
"exports": {
".": {
"import": "./dist/esm.js",
"require": "./dist/cjs.js",
"default": "./dist/cjs.js" // always last
}
}
}
// 5. "type" is exactly "module" or "commonjs" — no other value
Debugging Checklist
- Read the full error message — it includes the absolute path to the offending
package.json. Note whether it is your file or a dependency. - If it is your file: run
node -e "require('./package.json')"to surface the JSON syntax error with line and column. - If the JSON is syntactically valid: inspect the
"exports"field for mixed subpath and condition keys at the same level. - Check the
"type"field — it must be exactly"module"or"commonjs"; remove it entirely to default to CommonJS. - If it is inside
node_modules: deletenode_modulesandpackage-lock.json, runnpm cache clean --force, thennpm install. - Compare
node --versionbetween the working environment (local) and the failing one (CI/Docker) — newer Node.js may reject previously tolerated configs. - Check the dependency's GitHub issues and CHANGELOG for the error code — many popular packages (elasticsearch-js, stylis/emotion, USWDS) have had this exact bug.
- If no fixed version of the dependency exists, apply a patch with
patch-package. - For CI-generated
package.jsonfiles: addnode -e "require('./package.json') && console.log('valid')"as a validation step in your pipeline.
Frequently Asked Questions
What is ERR_INVALID_PACKAGE_CONFIG?
ERR_INVALID_PACKAGE_CONFIG is thrown by Node.js when it reads a package.json file and finds it either contains invalid JSON syntax or has a semantically invalid "exports", "imports", or "type" field. The error can come from your own package.json or from one inside node_modules.
How do I find which package.json is invalid?
The error message always includes the full file path. For example: Invalid package config /project/node_modules/some-package/package.json. Open that file to diagnose the problem. If it is your own package.json, run node -e "require('./package.json')" to get Node.js to point at the exact line and character.
How do I fix "exports cannot contain some keys starting with '.' and some not"?
This error means your exports object mixes subpath keys (starting with .) and bare condition keys (like import, require, default) at the same level. Nest all conditions under a "." key:
{
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"default": "./dist/cjs/index.js"
},
"./utils": "./dist/utils.js"
}
}
Why does ERR_INVALID_PACKAGE_CONFIG appear after upgrading Node.js?
Newer Node.js versions apply stricter validation to package.json fields. A package.json that was silently tolerated on Node.js 16 may throw on Node.js 20 or 22. The elasticsearch-js package triggered this for Node.js 23 users in 2024. Fix by updating the problematic dependency to a version with a corrected package.json, or use patch-package while waiting for the upstream fix.
Why does ERR_INVALID_PACKAGE_CONFIG appear in production but not locally?
The most common reason is a different Node.js version in production or CI. Run node --version in both environments. A secondary cause is that npm ci in CI installs an exact transitive dependency version from the lockfile that differs from what npm install resolved locally — one of those versions has an invalid package.json. Fix by ensuring your lockfile is committed and both environments use the same Node.js version.
How do I validate a package.json from the command line?
Three options, in order of usefulness:
node -e "require('./package.json')" — uses Node.js itself; prints SyntaxError with line/column on failure.
npx jsonlint package.json — dedicated linter with readable diff-style output.
python3 -m json.tool package.json — works on any machine with Python 3; no install needed.
ERR_INVALID_PACKAGE_CONFIG with pnpm or yarn clean install fix
The same clean-reinstall fix applies for pnpm and Yarn. For pnpm: rm -rf node_modules && pnpm store prune && pnpm install. For Yarn Classic: rm -rf node_modules yarn.lock && yarn cache clean && yarn install. For Yarn Berry (PnP): yarn cache clean && yarn install. The error almost always means a corrupted or partially written package.json inside the store or node_modules directory.
Does ERR_INVALID_PACKAGE_CONFIG only affect ESM projects?
No. While the exports field is most commonly used in ESM-aware packages, ERR_INVALID_PACKAGE_CONFIG is thrown for both require() (CommonJS) and import (ESM) when Node.js resolves a module and encounters an invalid package.json on the resolution path. A malformed JSON file in a CJS-only project will trigger the error just as quickly.
What Node.js versions enforce ERR_INVALID_PACKAGE_CONFIG?
The exports and imports field validation was introduced in Node.js 12.7 (unflagged in 12.17). Structural validation has tightened with every major Node.js release. Node.js 14+ enforces the no-mixed-keys rule for exports. Node.js 22 applies the strictest checks currently available. Node.js versions before 12.7 ignore the exports field entirely and would not throw this error for exports-related issues (but would still throw for malformed JSON).
Related Errors
ERR_PACKAGE_PATH_NOT_EXPORTED— thepackage.jsonis structurally valid but the subpath you are importing is not listed in the"exports"map; the complement to this errorERR_REQUIRE_ESM— thepackage.jsonis valid and has"type": "module", but you tried torequire()it instead of usingimportSyntaxError: Cannot use import statement outside a module— the inverse: your file uses ESM syntax but Node.js treats it as CJS because of the"type"fieldError: Cannot find module (MODULE_NOT_FOUND)— the file or package does not exist at all, versus existing but having an invalid configERR_UNSUPPORTED_DIR_IMPORT— your import targets a directory; often a companion error when migrating a package to use anexportsmap