Skip to content
Latchkey

Node ERR_MODULE_NOT_FOUND on ESM Import in CI - Fix Specifier Resolution

ERR_MODULE_NOT_FOUND is the ES module version of "cannot find module". The ESM loader does not guess extensions, so a bare relative import fails to resolve.

What this error means

A program run as ESM (type module or .mjs) throws Error [ERR_MODULE_NOT_FOUND] naming a relative import. The fix that worked under CommonJS (omitting .js) no longer applies.

node
node:internal/process/esm_loader:97
Error [ERR_MODULE_NOT_FOUND]: Cannot find module
'/home/runner/work/app/app/src/utils' imported from /home/runner/work/app/app/src/index.js
Did you mean to import ./utils.js?

Common causes

A relative import without a file extension

Native ESM requires the full path including .js; unlike CommonJS it will not append the extension for you.

Importing a directory without an explicit index file path

ESM does not auto-resolve ./dir to ./dir/index.js, so a directory import fails outright.

How to fix it

Add the explicit file extension

  1. Change bare relative imports to include the .js extension that the compiled output uses.
  2. Point directory imports at the concrete index.js file.
  3. Re-run the job to confirm the loader resolves it.
JavaScript
import { format } from './utils.js';
import config from './config/index.js';

How to prevent it

  • When compiling TypeScript to ESM, write .js extensions in source imports (or use a resolver that rewrites them) so the emitted code resolves under native ESM in CI.

Related guides

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