Skip to content

Unsupported character(s) in import module-name #41052

Description

@notroid5

Version

16.13.0

Platform

Microsoft Windows NT 10.0.19043.0 x64

Subsystem

No response

What steps will reproduce the bug?

  • create a file to run the code, e.g. server.js:
import { userZero } from './#user/user0.js'
console.log(userZero)
  • create package.json:
{
    "type": "module"
}
  • create a folder starting with # (probably not the only unsupported character), e.g. #user
  • create a file in this folder, e.g. user0.js:
export const userZero = 'This is a user.'

How often does it reproduce? Is there a required condition?

Node.js always throws an unconditional error during the import.

What is the expected behavior?

It should log the string.

What do you see instead?

PS D:\issue> node .\server.js
node:internal/process/esm_loader:94
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import 'D:\issue\' is not supported resolving ES modules imported from D:\issue\server.js
Did you mean to import ../#user/user0.js?
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:412:17)
    at moduleResolve (node:internal/modules/esm/resolve:932:10)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',
  url: 'file:///D:/issue/#user/user0.js'
}

Additional information

  • npm -v: 8.1.0
  • It does not matter whether a relative or absolute path is used, although the error is slightly different
  • Trying to escape \ the # does not work
  • If you remove the #, it works as expected
  • Node.js seems to think I want to import a directory before the #, yet is aware of the rest of the full path...?
  • The suggested solution ("Did you mean to import ...") is complete nonsense in this case
  • I couldn't find a list if unsupported characters for import module-names, so I have to assume there is none, which would mean that every character should be supported, especially since it's just a string pointing to a file
  • Thought I was going crazy when this simple import refused to work, so I made sure everything else works fine multiple times...

Edit: Typo

Activity

  1. devsnek commented on Dec 2, 2021

    @devsnek
    Member

    import specifiers are URLs. you'll need to replace # with %23 and \ with %5C

  2. added
    esmIssues and PRs related to the ECMAScript Modules implementation.
    on Dec 2, 2021
  3. notroid5 commented on Dec 2, 2021

    @notroid5
    ContributorAuthor

    Okay, that works but is this documented somewhere?
    And even if, import works with local paths, so it is expected to replace problematic characters by itself and not by the user.
    Which it clearly does not, ergo this issue.

  4. Trott commented on Dec 2, 2021

    @Trott
    Member

    Okay, that works but is this documented somewhere?

    Yes. https://nodejs.org/api/esm.html#urls

    ES modules are resolved and cached as URLs. This means that files containing special characters such as # and ? need to be escaped.

    There is probably room for improvement. For example, it could indicate the type of escaping, as escaping with \ won't work.

    If you or someone else reading this would like to suggest an improvement, you can click the "Edit On GitHub" link at the top of that page, or you can edit the doc/api/esm.md file in this repository and submit the change as a pull request.

  5. Trott commented on Dec 2, 2021

    @Trott
    Member

    And even if, import works with local paths, so it is expected to replace problematic characters by itself and not by the user.

    There's probably a discussion to be had about whether this calls for a doc enhancement, a change in the error message, or an actual change in the behavior of the ESM system. (I would imagine that last one seems unlikely to happen, but I'm not deeply engaged in the discussions around that stuff so I could be very wrong.) (Also, those three options are not mutually exclusive.)

    @nodejs/modules

  6. aduh95 commented on Dec 3, 2021

    @aduh95
    Contributor

    import works with local paths

    Well precisely it doesn't, hence your issue. If all the parts of your path only contains alphanumeric characters, and you are using an OS that accepts / to as path separator, you may think that those URLs are paths, but it's just a coincidence. On Windows, you may have noticed you cannot use \ to separate folders in the specifiers, no matter how you try to escape those, because it's not a path.

    So you are trying to specify a relative URL, the problem is that # is a special character for URLs:

    $ new URL('./#user/user0.js', 'file:///local/cwd/')
    URL {
    hash: "#user/user0.js"
    host: ""
    hostname: ""
    href: "file:///local/cwd/#user/user0.js"
    origin: "file://"
    password: ""
    pathname: "/local/cwd/"
    port: ""
    protocol: "file:"
    search: ""
    searchParams: URLSearchParams {}
    username: ""
    [[Prototype]]: URL
    }

    The same thing would appear if you were using ? in your directory name (although that's not a problem you can have on Windows, as it forbids use of ? in file names for some reason).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    esmIssues and PRs related to the ECMAScript Modules implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions