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.
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.
# run via the tsx CLI
npx tsx src/index.ts
# or register tsx for a plain node invocation
node --import tsx src/index.tsWire it into scripts consistently
- Put
tsxin devDependencies so the loader is installed in CI. - Use one invocation style (
tsxCLI or--import tsx) across the repo. - For ESM projects, ensure
"type": "module"matches how your TS is authored.
How to prevent it
- Always register tsx (
tsxCLI or--import tsx) before running .ts. - Keep tsx in devDependencies for CI.
- Avoid the deprecated
--loaderregistration.