# Node.js ESM "ERR_MODULE_NOT_FOUND" on Extensionless Imports

> Fix Node.js ESM "ERR_MODULE_NOT_FOUND" caused by extensionless relative imports - native ESM requires the .js extension that CommonJS let you omit.

Source: https://latchkey.dev/learn/node-js/node-err-module-not-found-extensionless  
Updated: 2026-06-25

Native ESM does not do CommonJS-style extension guessing. A relative import without a file extension that worked under CJS (or a bundler) fails under Node ESM with `ERR_MODULE_NOT_FOUND`.

## Diagnose it: what is different about the runner?

A build that passes locally and fails on a runner differs in a small number of predictable ways. Check those before changing build configuration, because the build config is usually not the thing that changed.

```.github/workflows/ci.yml
- run: |
    node --version && npm --version
    echo "NODE_ENV=$NODE_ENV  CI=$CI"
    nproc && free -h && df -h /
    ls -la node_modules/.bin | head
```

> `CI=true` is set on every runner and changes behaviour in several toolchains, most commonly by promoting warnings to errors. Reproduce locally with `CI=true npm run build` before assuming the runner is broken.

## The three that account for most of them

- **Case sensitivity.** Linux runners are case sensitive, macOS is not. An import with the wrong case resolves locally and fails in CI.
- **Out of memory.** Exit code 137 is a SIGKILL from the kernel, not a build error. Raise `--max-old-space-size` or use a larger runner.
- **devDependencies pruned.** `NODE_ENV=production` makes `npm ci` skip devDependencies, so the build tool itself goes missing. Set it after install, not before.

## FAQ

### What causes Node.js ESM "ERR_MODULE_NOT_FOUND" on extensionless imports?

There are 2 common causes: extensionless relative import under esm and typescript output without rewritten extensions. CommonJS and bundlers resolve ./util to ./util.js for you.

### How do I fix Node.js ESM "ERR_MODULE_NOT_FOUND" on extensionless imports?

There are 2 fixes depending on which cause you have: add explicit file extensions and configure typescript for node esm. Work through them in order, since the first is the most common.

### What does Node.js ESM "ERR_MODULE_NOT_FOUND" on extensionless imports actually mean?

After switching to "type": "module" or running compiled ESM, imports like import { x } from "./util" fail with ERR_MODULE_NOT_FOUND, even though ./util.js exists.

### How do I stop Node.js ESM "ERR_MODULE_NOT_FOUND" on extensionless imports happening again?

Always include file extensions in relative ESM imports. The prevention section lists 3 changes that keep it from recurring.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
