vitejs/vite · error · Error

Package subpath ' ' is not defined by "exports" in .

Error message

Package subpath '${relativeId}' is not defined by "exports" in ${path.join(dir, 'package.json')}.

What it means

During package resolution, Vite honors the 'exports' field of package.json. If the requested subpath does not match any exports entry (or exports is an array/non-object, treated as 'not exposed'), relativeId becomes undefined and Vite throws a Node-style ERR_PACKAGE_PATH_NOT_EXPORTED-style message naming the package.json path.

Solutions

  1. Import only the paths the package documents as exported (often just the package root).
  2. If you control the package, add the subpath to its 'exports' map.
  3. Check the package version against your assumption — a downgrade/upgrade may have changed exports.
  4. If a transitive dep is doing the bad import, update that dependency or open an issue upstream.

Example fix

// before
import _ from 'mylib/internal/util'
// after — use an exported path
import _ from 'mylib'
// or, if you own mylib, in package.json:
{ "exports": { ".": "./dist/index.js", "./internal/util": "./dist/internal/util.js" } }
Defensive patterns

Strategy: validation

Validate before calling

// Verify a subpath is exported before importing
import { resolveExports } from 'resolve.exports'
function assertExported(pkgJsonPath, subpath, conditions) {
  const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
  const resolved = resolveExports(pkg, subpath, { conditions })
  if (!resolved) throw new Error(`${subpath} is not exported by ${pkgJsonPath}`)
}

Type guard

function isExportedSubpath(pkg, subpath): boolean {
  const exp = pkg.exports
  if (!exp || typeof exp !== 'object' || Array.isArray(exp)) return false
  return subpath in exp || '.' in exp // simplified
}

Try / catch

try {
  return await import('pkg/subpath')
} catch (e) {
  if (/not defined by "exports"/.test(e.message)) {
    return await import('pkg') // fall back to root export
  }
  throw e
}

Prevention

When it happens

Trigger: Importing 'pkg/somesubpath' where pkg's package.json has an 'exports' map that does not list that subpath. The throw happens in resolvePackageImports when splitFileAndPostfix + resolveExportsOrImports returns undefined.

Common situations: Deep imports the package author did not export (e.g. 'lodash/fp/internal'), version upgrades that tightened the exports map, or a typo in the subpath. Also seen when a package switches from CommonJS (no exports) to ESM-with-exports and previously-working deep imports break.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/9d2e64769ea941e4. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/node/plugins/resolve.ts:1081

      const { file, postfix } = splitFileAndPostfix(relativeId)
      const exportsId = resolveExportsOrImports(
        data,
        file,
        options,
        'exports',
        externalize,
      )
      if (exportsId !== undefined) {
        relativeId = exportsId + postfix
      } else {
        relativeId = undefined
      }
    } else {
      // not exposed
      relativeId = undefined
    }
    if (!relativeId) {
      throw new Error(
        `Package subpath '${relativeId}' is not defined by "exports" in ` +
          `${path.join(dir, 'package.json')}.`,
      )
    }
  } else if (options.mainFields.includes('browser') && isObject(browserField)) {
    // resolve without postfix (see #7098)
    const { file, postfix } = splitFileAndPostfix(relativeId)
    const mapped = mapWithBrowserField(file, browserField)
    if (mapped) {
      relativeId = mapped + postfix
    } else if (mapped === false) {
      setResolvedCache(id, browserExternalId, options)
      return browserExternalId
    }
  }

  if (relativeId) {
    const resolved = tryFsResolve(

View on GitHub (pinned to b4d66fee14)