Node "ERR_UNKNOWN_FILE_EXTENSION: Unknown file extension .ts" in CI
Node ESM only knows how to load .js, .mjs, and .cjs. Pointing it at a .ts entry without a TypeScript loader (or older Node without --experimental-strip-types) throws ERR_UNKNOWN_FILE_EXTENSION.
What this error means
Running node src/index.ts or node --loader ts-node/esm fails with "TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension \".ts\" for /app/src/index.ts".
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for
/app/src/index.ts
at Object.getFileProtocolModuleFormat (node:internal/modules/esm/get_format:160:9)Common causes
No TypeScript loader registered for ESM
The ESM resolver has no hook for .ts, so without a loader Node cannot determine the module format.
Node version below the strip-types support
Native .ts execution needs a recent Node (--experimental-strip-types on 22.6+, default on 23.6+); older runners cannot run .ts directly.
How to fix it
Run via tsx, which handles .ts in ESM
tsx registers a loader so .ts files run without a separate build step.
npm install -D tsx
npx tsx src/index.tsOr enable native type stripping on Node 22.6+
Recent Node can strip TypeScript types at run time with a flag.
node --experimental-strip-types src/index.tsHow to prevent it
- Use tsx or a build step to run TypeScript under ESM.
- Pin a Node version that supports your chosen TS-run strategy.
- Avoid passing raw
.tsto a plainnodeinvocation.