Skip to content

[Auto-import] Quick Fix suggests invalid module specifiers that fail to resolve at runtime #64171

Description

🔎 Search Terms

Auto-import suggest invalid

🕗 Version & Regression Information

Tried in: 5.9.3., 6.0.3 and 7.0.2

⏯ Playground Link

No response

💻 Code

The project uses "module": "nodenext" and "moduleResolution": "nodenext" with the following "imports" configuration in package.json:

"imports": {
  "#*": {
    "node": "./dist/*/index.js",
    "default": "./dist/*.js"
  }
}

Project structure:

src/
  utils/
    summarize/
      index.ts      // re‑exports summarize from summarize.ts
      summarize.ts  // export const summarize
  index.ts          // file where auto‑import is triggered

./vscode/settings.json:

  "editor.codeActionsOnSave": {
    "source.addMissingImports": "always",
    "source.fixAll.prettier": "never",
    "source.fixAll": "explicit"
  },
  "js/ts.preferences.importModuleSpecifier": "non-relative",

Steps to reproduce:
In src/index.ts, start typing summarize.
Trigger the Quick Fix / auto‑import suggestions.

🙁 Actual behavior

With the "node" condition active and "js/ts.preferences.importModuleSpecifier": "non-relative" set, the LSP (Quick Fix) offers two alias suggestions for the same symbol:

  • #utils/summarize - resolves correctly via "node" to ./dist/utils/summarize/index.js.
  • #utils/summarize/summarize - would resolve only via the "default" condition, which is not active at runtime.

Selecting the second suggestion causes a runtime error:
node:internal/modules/esm/resolve:272 throw new ERR_MODULE_NOT_FOUND...

🙂 Expected behavior

Node.js uses only the first matching condition based on the active conditions.
The second alias is therefore never considered at runtime.

The auto‑import should suggest only valid module specifiers that matches the active conditions.

For example, both suggestions would be valid if the node condition were removed.

Additional information about the issue

The behavior is not limited to nodenext; it also occurs with other resolution modes and with customConditions.

Related issue: #62439, #50762

Would not be a breaking change for LSP suggestions (Quick Fix / Auto Fix), as they would simply no longer offer specifiers that are unresolvable at runtime.

Update – additional case with paths in tsconfig.json
The issue also occurs when combining "imports" (in package.json) and "paths" (in tsconfig.json). For example:

// package.json
"imports": {
  "#*": "./dist/*/index.js"
}

// tsconfig.json
"paths": {
  "#*": ["./src/*"]
}

With this setup, the Quick Fix suggests:
import { summarize } from "#utils/summarize"; -> valid.
import { summarize } from "#utils/summarize/summarize.js"; -> ERR_MODULE_NOT_FOUND

Activity

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

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions