Skip to content
Latchkey

Node tsx/ts-node Runtime Resolution Error in CI - Fix the TypeScript Loader

tsx and ts-node run TypeScript through a custom loader. Resolution errors appear when the loader, the module setting, and import extensions disagree.

What this error means

Running TS directly with tsx or ts-node fails in CI with a resolution error (cannot find module or unknown extension) even though tsc compiles the project fine.

node
TypeError [ERR_MODULE_NOT_FOUND]: Cannot find module
'/home/runner/work/app/app/src/utils' imported from
/home/runner/work/app/app/src/index.ts
    at finalizeResolution (node:internal/modules/esm/resolve:264:11)

Common causes

Extensionless imports under ESM resolution

In ESM mode the loader does not append .ts/.js, so a bare relative import fails to resolve.

A loader and tsconfig module mismatch

The ts-node/tsx loader expects one module system while tsconfig targets another, so resolution diverges from tsc.

How to fix it

Use tsx, which handles extensions

  1. Run the TypeScript entry through tsx in CI.
  2. Use the same command locally.
GitHub Actions
- run: npx tsx src/index.ts

Align ts-node ESM settings

  1. Enable ts-node ESM support and allow .ts extensions in imports.
  2. Match the tsconfig module setting to the loader mode.
tsconfig.json
// tsconfig.json
"ts-node": { "esm": true, "experimentalSpecifierResolution": "node" }

How to prevent it

  • Pick one TypeScript runner and keep its loader, the tsconfig module setting, and import-extension style consistent between local dev and CI.

Related guides

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