Skip to content
Latchkey

Node.js ERR_UNSUPPORTED_DIR_IMPORT - Fix Directory Import in ESM

Native ESM does not do the CommonJS folder-resolution dance. Importing a directory and expecting Node to find its index.js silently is a CJS-only behavior that ESM removed.

What this error means

Under "type": "module" (or a .mjs file), an import that points at a folder - expecting index.js to be picked up - fails with ERR_UNSUPPORTED_DIR_IMPORT. The same import worked in CommonJS.

Node output
Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/app/src/utils'
is not supported resolving ES modules imported from /app/src/index.js
Did you mean to import ./utils/index.js?
    code: 'ERR_UNSUPPORTED_DIR_IMPORT'

Common causes

Importing a folder under native ESM

CommonJS auto-resolves ./utils to ./utils/index.js. ESM does not - it requires the exact file path with its extension, so a bare directory import fails.

A CJS codebase moved to "type": "module"

Flipping a package to ESM exposes every implicit directory/extensionless import that the CJS resolver previously tolerated.

How to fix it

Import the explicit file with its extension

Point at the actual file, including the .js extension ESM requires.

JavaScript
// CJS-style (fails in ESM):
import { x } from './utils'

// ESM-correct:
import { x } from './utils/index.js'

Or restore folder resolution deliberately

  1. For a large migration, a custom resolver/loader can re-add index resolution - but prefer fixing imports.
  2. If TypeScript-compiled, set the module resolution so emitted imports carry extensions (e.g. NodeNext).
  3. Add a lint rule requiring explicit extensions so new directory imports are caught in review.

How to prevent it

  • Always import explicit files with extensions under ESM.
  • Use NodeNext module resolution in TypeScript ESM projects.
  • Lint for extensionless/directory imports.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →