Skip to content

ERR_UNKNOWN_FILE_EXTENSION for binaries without extension #1943

Closed
@emoriarty

Description

@emoriarty

Search Terms

ERR_UNKNOWN_FILE_EXTENSION, entrypoint, runmain

Expected Behavior

Running ts-node-esm for binaries with no extension work without error in node 18.6 and greater.

Actual Behavior

Executing ts-node-esm for binaries without extension (sequelize, uuid, tserver) throws the following error:

CustomError: ERR_UNKNOWN_FILE_EXTENSION  /Users/enriquearias/Workspace/swile/notifications-hub/node_modules/uuid/dist/bin/uuid
    at defaultGetFormat (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/dist-raw/node-internal-modules-esm-get_format.js:93:15)
    at defer (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/src/esm.ts:307:38)
    at entrypointFallback (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/src/esm.ts:314:14)
    at getFormat (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/src/esm.ts:352:17)
    at /Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/src/esm.ts:268:10
    at addShortCircuitFlag (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/dist/esm.js:233:23)
    at load (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/dist/esm.js:122:16)
    at load (/Users/enriquearias/Workspace/swile/notifications-hub/node_modules/ts-node/src/child/child-loader.ts:18:36)
    at nextLoad (node:internal/modules/esm/loader:163:28)
    at ESMLoader.load (node:internal/modules/esm/loader:605:26)

This error happens only in node v18.6 and higher.

Minimal reproduction

Here's a minimal reproduction repository to test it.

Specifications

  • ts-node version: 10.9.1
  • node version: >= 18.6.0
  • TypeScript version: 4.9.4
  • Operating system and version: Mac OSX | Ubuntu

Debug

After debugging the source code, I've noticed that the last version (10.9.1) includes this patch which causes the issue here.

Concretely, the file runmain-hack.js is importing the entrypoint file (uuid in the example above) which adds itself as parentURL in the current import context.

When the entrypointFallback function is executed, it is asked if the current file (specifier) is an entrypoint by calling the function isProbablyEntrypoint.

One of the conditions to be a entrypoint in isProbablyEntrypoint is that there's no parent in the context. Because runmain-hack adds the parent in the context, the rememberIsProbablyEntrypoint object won't be updated.

This is important for files without extension, because when the function getFormat executes the defaultGetFormat which throws an error because there's no matching format, the catch body checks if the file is an entrypoint. But, because the rememberIsProbablyEntrypoint was not set, instead of returning the commonjs format, the error is re-thrown.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions