Skip to content
Latchkey

tsx "Unknown file extension .ts" - Fix tsx Registration with --import in CI

tsx transforms TypeScript/ESM on the fly, but only once its loader is registered. If you run node app.ts without registering tsx (or use a stale --loader form), Node sees a .ts file it cannot parse and throws an unknown-extension error.

What this error means

Running a TypeScript entry under Node fails with ERR_UNKNOWN_FILE_EXTENSION: Unknown file extension ".ts", even though tsx is installed. tsx was never registered for that invocation, so Node tried to load the .ts file natively.

Node output
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"
for /app/src/index.ts
    at Object.getFileProtocolModuleFormat (node:internal/modules/esm/get_format)
    code: 'ERR_UNKNOWN_FILE_EXTENSION'

Common causes

tsx was not registered for the run

Invoking node src/index.ts directly does not enable tsx. Without registration Node has no transformer for .ts, so the extension is unknown.

Using the deprecated --loader form

An older --loader tsx/esm invocation may warn or, on newer Node, not register as expected; the current pattern is --import tsx (or the tsx CLI).

How to fix it

Register tsx with --import or run the tsx CLI

Use the current registration entry so Node hands .ts files to tsx.

Terminal
# run via the tsx CLI
npx tsx src/index.ts

# or register tsx for a plain node invocation
node --import tsx src/index.ts

Wire it into scripts consistently

  1. Put tsx in devDependencies so the loader is installed in CI.
  2. Use one invocation style (tsx CLI or --import tsx) across the repo.
  3. For ESM projects, ensure "type": "module" matches how your TS is authored.

How to prevent it

  • Always register tsx (tsx CLI or --import tsx) before running .ts.
  • Keep tsx in devDependencies for CI.
  • Avoid the deprecated --loader registration.

Related guides

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