Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSCode doesn't run ESLint Server with eslint.config.js flat config #1620

Closed
eakl opened this issue Mar 13, 2023 · 74 comments
Closed

VSCode doesn't run ESLint Server with eslint.config.js flat config #1620

eakl opened this issue Mar 13, 2023 · 74 comments
Labels
info-needed Issue requires more information from poster

Comments

@eakl
Copy link

eakl commented Mar 13, 2023

VSCode is not running ESLint server on my codebase when using the new ESLint Flat Config eslint.config.js.

I have the following setup:

  • The app is a Vite + Svelte + TS starter
  • The issue happens in a monorepo (pnpm workspace)
  • ESLint correctly lint my codebase when invoked via the CLI pnpm eslint src
  • Packages has been reinstalled several times with pnpm install and the ESLint server has been restarted
  • VSCode doesn't run ESLint server on my codebase when using the flat config

My codebase structure

/client
   /.vscode
      settings.json
   /src
      main.ts
      App.svelte
   eslint.config.js
   package.json
   vite.config.ts
package.json
pnpm-workspace.yaml

ESLint correctly lint my codebase with pnpm eslint src and find errors in both src/main.ts and src/App.svelte.

But VSCode is unable to run the ESLint server with eslint.config.js located at the workspace root

The Output console says

[Info  - 5:43:59 PM] ESLint server is starting.
[Info  - 5:44:00 PM] ESLint server running in node v16.14.2
[Info  - 5:44:00 PM] ESLint server is running.
[Info  - 5:44:00 PM] 
Failed to load the ESLint library for the document <project_root>/client/src/App.svelte

To use ESLint please install eslint by running pnpm install eslint in the workspace folder test
or globally using 'pnpm install -g eslint'. You need to reopen the workspace after installing eslint.

Alternatively you can disable ESLint for the workspace folder test by executing the 'Disable ESLint' command.

My settings.json located at client/.vscode/settings.json

{
  "css.lint.unknownAtRules": "ignore",
  "scss.lint.unknownAtRules": "ignore",
  "eslint.enable": true,
  "eslint.packageManager": "pnpm",
  "eslint.format.enable": true,
  "eslint.validate": [
    "javascript",
    "typescript",
    "svelte"
  ],
  "eslint.experimental.useFlatConfig": true,
  "eslint.workingDirectories": [{ "mode": "auto" }],
  "eslint.options": {
    "overrideConfigFile": "./eslint.config.js"
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}
@MariaSolOs
Copy link
Member

For an easier investigation, it would be good to provide a repo with a minimal project that reproduces the issue.

@dbaeumer dbaeumer added the info-needed Issue requires more information from poster label Mar 14, 2023
@eakl
Copy link
Author

eakl commented Mar 16, 2023

Context

  • I share 2 monorepos implementing the new ESLint flat config
  • Both monorepos consist of a root project and multiple subprojects in the playground folder (vanilla JS, React JS/TS, Svelte JS/TS)
  • The first monorepo has one eslint.config.js located at the root of the monorepo
  • The second monorepo has multiple eslint.config.js located in each of the subprojects located in the playground folder
  • To See ESLint in action, open counter.{js,ts,svelte} or App.{jsx,tsx} in each subproject

First Repo

  • The root is a vite/svelte project
  • eslint.config.js is located at the root of the project

VSCode seems to work for all subprojects but not for the root (open Counter.svelte)

Second Repo

  • This repo consists of a library that need to be built. It is an ESLint sharable config project
  • The root project is the sharable config for multiple extensions
  • In the playground folder, each subproject has eslint and the sharable config installed as dependencies. They all have an eslint.config.js at their root.

VSCode doesn't seems to work in this case (open each counter.{js,ts,svelte} or App.{jsx,tsx})

@dbaeumer
Copy link
Member

Flat configs are still experimental and need to be enabled in VSCode ESLint using the eslint.experimental.useFlatConfig setting. I could not find such a setting in the repositories. Do you enable it?

@eakl
Copy link
Author

eakl commented Mar 17, 2023

I has been excluded by my .gitignore but I do have it both of my repos. I have updated the repos with my .vscode/settings.json

EDIT

I have tried to open VSCode at /test which is not a monorepo, just the folder where I have both of my monorepos. ESLint doesn't work at all.

test/
   /eslint-flat-vscode-root
   /eslint-flat-vscode-playground

It seems like the extension has issue traversing the project tree to look for the closest eslint.config.js

@dbaeumer
Copy link
Member

Regarding Svelte files: they are currently not autodetected in the ESLint extension. See #1468. So you need to configure the eslint.validate setting. Please note that if you specify that setting you need to list all language ids you want to see validated including TypeScript and JavaScript.

@dbaeumer
Copy link
Member

For there second repro this is very likely a working directory issue. Have you tried to list the playground directories containing a eslint.config.js file as a working directory (e.g. eslint.workingDirectories setting).

ESLint is very sensitive in regards to the working directory used when searching for configuration files.

@eakl
Copy link
Author

eakl commented Mar 20, 2023

I have tried multiple options

"eslint.workingDirectories": [
    { "pattern": "./playground/*/" }
  ],
"eslint.workingDirectories": ["...", "./playground/20-react-ts", "..."]
"eslint.workingDirectories": [{ "mode": "auto" }]
"eslint.workingDirectories": [{ "mode": "location" }]

When running eslint cli I get this error

~/d/t/eslint-flat-vscode-playground main ❯ pnpm eslint .                       

Oops! Something went wrong! :(

ESLint: 8.36.0

ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:

    npm init @eslint/config

ESLint looked for configuration files in /Users/eliasaboukhalillanvin/dev/test/eslint-flat-vscode-playground/dist and its ancestors. If it found none, it then looked in your home directory.

If you think you already have a configuration file or if you need more help, please stop by the ESLint Discord server: https://eslint.org/chat

@dbaeumer
Copy link
Member

The ESLint extension depends on a proper setup ESLint. If running ESLint in the terminal fails it will very likely fail with the extension as well. What I would recommend is to get it working in the terminal and then take it to the extension. If it works in the terminal but not in the extension I can definitely have a look.

@azat-io
Copy link

azat-io commented Apr 27, 2023

The same problem 😢

@tdfranklin
Copy link

@dbaeumer

I am also running into a the same (or at least very similar) issue. I am able to run ESLint in the terminal, however I am not seeing the errors in the VSCode editor using the new flat config. I created a quick sample repo so you can take a look:

https://github.com/tdfranklin/eslint-test

If you run pnpm lint, you should see 3 errors in App.tsx, however when I open the file in VSCode, I don't see any errors or warnings.

@dbaeumer
Copy link
Member

Works for me

image

Please note that in ESLint extension you still need to enable flat config. The reason is that we need to call different API in ESLint and we need to find a way to abstract that. The setting is:

{
    "eslint.experimental.useFlatConfig": true
}

@azat-io
Copy link

azat-io commented May 18, 2023

@dbaeumer It works! Thanks a lot!

@tdfranklin
Copy link

Very strange - I do have the flag enabled, but I'm getting this error in the output:

image

I thought it might be something to do with it being a monorepo and not ignoring all node_modules folder's, but maybe on of my other VSCode settings is blocking it?

@dbaeumer
Copy link
Member

@tdfranklin does it work in the terminal when executing ./node_modules/.bin/eslint apps/client/src/App.tsx

@tdfranklin
Copy link

tdfranklin commented May 19, 2023

@dbaeumer - Yes, when I run it in the terminal, I don't see any errors.

Today I'm going to move my tsconfig and eslint config to shared workspace packages instead of having them in the root directory and see if that changes anything, so I'll update once I finish if I'm still seeing errors.

@tdfranklin
Copy link

tdfranklin commented May 19, 2023

RESOLVED - I'm leaving the comments below in case they help anyone in the future, but I think I've resolved this issue. After adding the following to my VSCode settings, it seems to be working correctly. Now to see if I can get it to work with the new flat config!

"eslint.workingDirectories": [
    { "pattern": "./apps/*/" },
    { "pattern": "./packages/*/" }
  ]

@dbaeumer - First of all, thank you so much for your help! I've been fighting with trying to get this working all week and it's probably something really obvious that I'm missing, but I just can't put my finger on it....

So first, the new folder structure:

- trinity (root folder)
  - apps
    - dealer
      - src
        - (...all project files)
      - package.json
      - tsconfig.json
      - .eslintrc.json
  - packages
    - tsconfig
      - base.json
      - package.json
    - eslint-config-custom
      - index.js
      - package.json
package.json
pnpm-workspace.yaml

A little bit of additional info - everything was working correctly before moving to a pnpm workspaces monorepo, both in the CLI and UI layers. To try and simplify the issue, I reverted back to the old eslint config and get that working first (as I'm now having issues with getting that to even work in the UI).

Here's all the relevant config files:

-- ROOT CONFIG FILES --

package.json

{
  "name": "trinity-frontend",
  "version": "0.0.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dealer": "pnpm --filter @trinity/dealer",
    "clean": "find ./ -name node_modules -type d -exec rm -rf {} +"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "prettier": "^2.8.4",
    "typescript": "^4.9.5"
  }
}

pnpm-workspace.yaml

packages:
- apps/*
- packages/*

-- TYPESCRIPT CONFIG FILES --

/packages/tsconfig/package.json

{
  "name": "@trinity/tsconfig"
}

/packages/tsconfig/base.json

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true, 
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "ESNext", 
    "moduleResolution": "Node", 
    "resolveJsonModule": true,
    "isolatedModules": true, 
    "noEmit": true, 
    "jsx": "react-jsx", 
    "outDir": "dist", 
    "incremental": true, 
    "noImplicitAny": true,
    "sourceMap": true,
    "importHelpers": true, 
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true
  },
  "exclude": ["node_modules"]
}

-- ESLINT CONFIG FILES --

/packages/eslint-config-custom/package.json

{
  "name": "eslint-config-custom",
  "main": "index.js",
  "version": "1.0.0",
  "dependencies": {
    "@typescript-eslint/eslint-plugin": "^5.53.0",
    "@typescript-eslint/parser": "^5.53.0",
    "eslint": "^8.35.0",
    "eslint-config-prettier": "^8.6.0",
    "eslint-import-resolver-typescript": "^3.5.3",
    "eslint-plugin-import": "^2.27.5",
    "eslint-plugin-jsx-a11y": "^6.7.1",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-simple-import-sort": "^10.0.0"
  }
}
/packages/eslint-config-custom/index.js

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: './tsconfig.json',
  },
  extends: [
    'eslint:recommended',
    'plugin:jsx-a11y/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:react/jsx-runtime',
    'plugin:import/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  plugins: ['react', 'prettier', 'import', 'jsx-a11y', '@typescript-eslint', 'simple-import-sort'],
  settings: {
    react: {
      version: 'detect',
    },
    'import/resolver': {
      typescript: {
        paths: './tsconfig.json',
        alwaysTryTypes: true,
      },
    },
  },
  globals: {
    React: true,
    JSX: true,
    __APP_VERSION__: true,
  },
  rules: {REMOVED FOR BREVITY},
}

-- APP CONFIG FILES --

/apps/dealer/package.json

{
  "name": "@trinity/dealer",
  "version": "3.2.7",
  "main": "index.tsx",
  "private": true,
  "dependencies": { REMOVED FOR BREVITY  },
  "devDependencies": {
    "@trinity/tsconfig": "workspace:^",
    "eslint-config-custom": "workspace:^",
  },
}

/apps/dealer/tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "extends": "@trinity/tsconfig/base.json",
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

/apps/dealer/.eslintrc.json

{
  "root": true,
  "extends": ["custom"]
}

So now what's happening is there seems to be a discrepancy between the CLI and UI on where the tsconfig.json file lives... with the config above, the CLI tool seems to lint the project correctly, however the UI is looking for a tsconfig file in the root directory. So when I update the eslint config file to point to apps/dealer/tsconfig.json then the UI will lint, but the CLI stops working.

Also, I'm not sure if I'm better off trying to keep the config in separate packages the way I have it above or going back and just keeping all of the config in the root directory? While I only have a single app at the moment, I'm trying to prepare the repo to add several more apps and packages and I want to keep it as simple as possible to share both eslint and typescript across the entire project. Any help you could offer would be so appreciated! Thank you!

@tdfranklin
Copy link

@dbaeumer - Ok, sorry for the sidetrack, but we're back to the original issue. So after getting everything working in the monorepo with the old .eslintrc* file, I tried moving back to the new flat config and am running into the same issue as above.

When running the CLI, it successfully lints the project:

image

However, I am getting the same error in the ESLint console for the UI:

image

Do you have any idea what's going on here? Perhaps some other setting I need to tweak in VSCode? (And yes, I made sure to turn back on the flat config option in VSCode):

image

@dbaeumer
Copy link
Member

Can I reproduce that in the repository you provided?

@tdfranklin
Copy link

@dbaeumer - Sorry for the delay, it's been a crazy day, but I just updated that repo to reproduce the same issue.

So currently I have it setup to use the new flat config and it lints from the command line, but on the UI, I am getting the same "unexpected key" error as show above. I also have it setup to swap to the old .eslintrc* style config and that works both on the command line and UI. If you want to switch between the two, in /packages/eslint-config/package.json change the "main" export file to oldConfig.cjs, then in /apps/client/package.json update the lint script to use flat config to be false and then (obviously) disable the setting in VSCode and restart the ESLint server and you will see that both sides work fine. However, with the flat config, the CLI works, but the UI gives that error.

Hopefully that makes sense, but just shout at me if I can provide any additional information. And thank you again for investigating this issue!

@levino
Copy link

levino commented May 23, 2023

I have a very similar issue. In my case I want to use a flat config AND yarn with pnp. Does not work. Only if I switch to nodeLinker: node-modules in my .yarnrc.yml.

@dbaeumer
Copy link
Member

@levino yarn with pnp needs special setup on the yarn side to work with VS Code. Have you followed the steps here: https://yarnpkg.com/getting-started/editor-sdks

@dbaeumer
Copy link
Member

@tdfranklin I pulled from that repository and when trying to run eslint in the terminal it actually fails very early with

/workspaces/eslint-test (main) $ ./node_modules/.bin/eslint apps/client/src/App.tsx

Oops! Something went wrong! :(

ESLint: 8.35.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'globals' imported from /workspaces/eslint-test/eslint.config.js
Did you mean to import globals@13.20.0/node_modules/globals/index.js?
    at new NodeError (node:internal/errors:399:5)
    at packageResolve (node:internal/modules/esm/resolve:794:9)
    at moduleResolve (node:internal/modules/esm/resolve:843:20)
    at ESMLoader.defaultResolve (node:internal/modules/esm/resolve:1058:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:323:32)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:172:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36)

I did run pnpm install before

Anything missing?

@levino
Copy link

levino commented May 23, 2023

Yes. I use a legacy config now with pnp and it works fine.

@tdfranklin
Copy link

tdfranklin commented May 23, 2023

@dbaeumer - That's very odd, globals is included in the eslint-config package.json dependencies so it should have installed...

update For simplicity, I just removed the code that was using globals as it's not part of this issue, so if you pull down the changes, you shouldn't have that issue anymore. Thank you!

@dbaeumer
Copy link
Member

@tdfranklin I pulled and the problem with that setup is now that you need to define a working directory since running eslint in the workspace folder root doesn't work either. It produces

/workspaces/eslint-test (main) $ ./node_modules/.bin/eslint apps/client/src/App.tsx

Oops! Something went wrong! :(

ESLint: 8.35.0

Error: ESLint configuration in apps/client/.eslintrc.json » eslint-config-trinity is invalid:
        - Property "" is the wrong type (expected object but got `"import rules from './flatConfig/index.js'\nexport default rules"`).

Referenced from: /workspaces/eslint-test/apps/client/.eslintrc.json
    at ConfigValidator.validateConfigSchema (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
    at ConfigArrayFactory._normalizeConfigData (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
    at ConfigArrayFactory._loadConfigData (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
    at ConfigArrayFactory._loadExtendedShareableConfig (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
    at ConfigArrayFactory._loadExtends (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
    at _normalizeObjectConfigDataBody.next (<anonymous>)
    at ConfigArrayFactory._normalizeObjectConfigData (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
    at _normalizeObjectConfigData.next (<anonymous>)
    at ConfigArrayFactory.loadInDirectory (/workspaces/eslint-test/node_modules/.pnpm/@eslint+eslintrc@2.0.3/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2865:28)

whereas this works: /workspaces/eslint-test/apps/client (main) $ ../../node_modules/.bin/eslint src/App.tsx

So you need to specify apps/client as a working directory using eslint.workingDirectories setting

@dbaeumer
Copy link
Member

image

@tdfranklin
Copy link

@dbaeumer

I did set that up:

image

However, I am still getting the same error:

image

@dbaeumer
Copy link
Member

@tdfranklin hmm, that is very wired since I could get the test repository working with this setup without any problem. What is wired as well is the fact that the error happens in ESLint npm itself when they read the flat config not in the extension code.

When you run it is the terminal are you using something like this: /workspaces/eslint-test/apps/client (main) $ ../../node_modules/.bin/eslint src/App.tsx

Don't go through pnpm run since this might tweak things in a different way not available in the extension.

@tdfranklin
Copy link

@dbaeumer Yea, it's very strange. For me, the CLI tool works fine (both with the method you listed above and just using pnpm lint. Both ways seem to lint the file and return the correct output, it's only when I turn on the VSCode flag and try to use the UI that I get the output listed above in the ESLint console.

I'm not sure if the environment might be a factor, but I am using WSL on Windows 10, so maybe that is causing the issue?

@aleksey-hoffman
Copy link

aleksey-hoffman commented Feb 23, 2024

Same issue with latest version of vscode and eslint.
VScode is not running eslint if I have a flat config enabled.
How come VSCode is unable to automatically check for existence of eslint.config.js?

@skondrashov
Copy link

skondrashov commented Feb 29, 2024

locateConfigFileToUse() is getting passed the root directory that vscode has opened instead of the directory that contains package.json. If you use vscode to open the directory that has package.json immediately inside it as the root it will find the file (or an even deeper directory, since it goes up until it finds the config).

You need to set the eslint.workingDirectories setting correctly if you are encountering this. Eslint used to look for a config file relative to the file you are linting, now I guess this call is required. I'm not sure what, if anything, this extension can do to make this less painful in the future, it kind of seems like eslint screwed us over.

@Elxx
Copy link

Elxx commented Mar 17, 2024

Ran into the same issue today, weirdly enough what solved it for me was renaming the eslint.config.js files in my workspace projects to eslint.config.cjs (and porting them to CommonJS by changing import to require, export to module.exports etc) and adding this to my workspace config:

  "eslint.experimental.useFlatConfig": true,
  "eslint.workingDirectories": [{ "mode": "auto" }]

Seems like the .js and .mjs variants don't get loaded properly by the extension but .cjs works fine. My packages all have "type": "module" in their package.json so everything else is ESM except this...

@dbaeumer
Copy link
Member

@Elxx this works for me and I have added a mjs example to the repository (see

)

If you can still not get it to work please provide me with a GitHub repository with a minimal setup I can clone that demos the problem.

@AndyOooh
Copy link

"eslint.experimental.useFlatConfig": true,
This works for me but it seems to disable legacy config files.
Would be nice if I could have both options on but I guess that's not possible?

@dbaeumer
Copy link
Member

Will come with the next release.

@davidkarlsson
Copy link

davidkarlsson commented Mar 28, 2024

I tested this with the vscode-eslint 3.0.3 alpha together with Yarn 4.1.1 in PnP mode using Eslint 8.57.0 and for me it seems like imports are not found when using a mjs config file but it works with a CommonJS config file.

With the mjs config I get an error like this one for whatever the first import happen to be in eslint.config.mjs:

[Error - 12:22:05 PM] An unexpected error occurred:
[Error - 12:22:05 PM] Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from D:\Test\eslint.config.mjs
Did you mean to import @eslint-js-npm-8.57.0-00ead3710a-3c501ce8a9.zip/node_modules/@eslint/js/src/index.js?
    at new NodeError (node:internal/errors:405:5)
    at packageResolve (node:internal/modules/esm/resolve:893:9)
    at moduleResolve (node:internal/modules/esm/resolve:942:20)
    at defaultResolve (node:internal/modules/esm/resolve:1135:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36)

The mjs config file works fine when I run eslint from the cli though and I also ran yarn dlx @yarnpkg/sdks after updating eslint and the extension but it didn't make any difference.

Like @Elxx said it does work if I change the config file to CommonJS instead so it seems like the problem lies in that it can't handle config files that are ES modules?

The only eslint related settings I've set in .vscode\settings.json are these now that eslint.experimental.useFlatConfig isn't needed any longer:

"eslint.nodePath": ".yarn/sdks",
"eslint.workingDirectories": [{ "mode": "auto" }],

@dbaeumer
Copy link
Member

@davidkarlsson can you please provide me with a GitHub repository I can clone with a minimal setup that demos this. I did setup my own test case with mjs and that works for me. So there must be something in the setup that doesn't make that work.

@davidkarlsson
Copy link

@dbaeumer I've managed to recreate it with vscode-eslint 3.0.3 in this repo if you want to take a look: https://github.com/davidkarlsson/vscode-eslint-test.

With eslint.config.cjs eslint works in both vscode-eslint and the cli but with the eslint.config.mjs it only works from the cli and with vscode-eslint I get the ERR_MODULE_NOT_FOUND error.

Also, it didn't make any difference setting the pnpEnableEsmLoader to true in .yarnrc.yml which I initially thought might be the issue. I think maybe that loader is enabled by default now in Yarn 4.x since it adds .pnp.loader.mjs even without a yarnrc file?

@dbaeumer
Copy link
Member

dbaeumer commented Apr 2, 2024

@davidkarlsson thanks for the repro. Got already fixed in latest which is available as a alpha release here: https://github.com/microsoft/vscode-eslint/releases/tag/3.0.5-alpha.1

Image

@davidkarlsson
Copy link

@dbaeumer That is strange because I get the same error with 3.0.5 as I did with 3.0.3 with the mjs config. test.ts doesn't show the linting errors and the output log logs this error:

[Info  - 2:27:54 PM] ESLint server is starting.
[Info  - 2:27:54 PM] ESLint server running in node v18.17.1
[Info  - 2:27:54 PM] ESLint server is running.
[Info  - 2:27:55 PM] ESLint library loaded from: D:\vscode-eslint-test\.yarn\sdks\eslint\lib\api.js
[Error - 2:27:55 PM] Calculating config file for file:///d%3A/vscode-eslint-test/test.ts) failed.
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from D:\vscode-eslint-test\eslint.config.mjs
Did you mean to import @eslint-js-npm-8.57.0-00ead3710a-10c0.zip/node_modules/@eslint/js/src/index.js?
    at new NodeError (node:internal/errors:405:5)
    at packageResolve (node:internal/modules/esm/resolve:893:9)
    at moduleResolve (node:internal/modules/esm/resolve:942:20)
    at defaultResolve (node:internal/modules/esm/resolve:1135:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36)

Perhaps there's something with my environment or Yarn installation that's causing this issue then. I just don't understand what it could be. I also noticed @bppdddqqqq had the same problem as me according to a comment here: #1644 (comment) but I think that was with an older version.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 2, 2024

Here is what I did:

  • cloned your repository
  • yarn install
  • opened VS Code with ESLint extension 3.0.5
  • opened test.ts

Any additional info?

@davidkarlsson
Copy link

I thought that would be enough to reproduce the issue so I'm not sure what additional info I can give you unfortunately. I've tried running the repro on multiple computers now (one running win10 and the other win11) but I get the same error on both of them so I'm at a loss of what could be the cause of this.

Do you have any ideas? The only thing I could think of was the node version so I tried setting eslint.runtime to node to change the node version eslint uses from v18.17.1 to my system version which is v20.12.0 but that also didn't make any difference.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 3, 2024

I was able to reproduce this. It seems that you need to have corepack enabled so that yarn does the right thing.

This being said I do think that this comes from some PnP stuff yarn does. I can reproduce the same problem using simple eslint API. The following code:

PowerShell:

> $env:NODE_PATH=".yarn/sdks"

This is what yarn does when running the editor SDK for VS Code (see https://yarnpkg.com/getting-started/editor-sdks)

const library = require(`eslint`);

async function main() {
	const eslint = new (await library.loadESLint({ useFlatConfig: true }))();
	const report = await eslint.lintText(`var test = "hello";`);
	console.log(report);
}

main().catch((error) => {
	console.error(error);
	process.exit(1);
});

produces the exact same error:

bugs\vscode-eslint-test [main ≡ +0 ~1 -0 | +1 ~1 -0 !]> node
Welcome to Node.js v18.18.2.
Type ".help" for more information.
> const library = require(`eslint`);
undefined
> library
{
  Linter: [class Linter],
  loadESLint: [AsyncFunction: loadESLint],
  ESLint: [class ESLint] { configType: 'eslintrc' },
  RuleTester: [class RuleTester] {
    [Symbol(itOnly)]: null,
    [Symbol(it)]: null,
    [Symbol(describe)]: null
  },
  SourceCode: [class SourceCode extends TokenStore]
}
> async function main() { const eslint = new (await library.loadESLint({ useFlatConfig: true }))(); const report = await eslint.lintText(`var test = "hello";`); console.log(repo
rt); }
undefined
> main().catch((error) => { console.error(error); process.exit(1); });
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 117,
  [Symbol(trigger_async_id_symbol)]: 114
}
> Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@eslint/js' imported from C:\xxxxxxxxx\bugs\vscode-eslint-test\eslint.config.mjs
Did you mean to import @eslint-js-npm-8.57.0-00ead3710a-10c0.zip/node_modules/@eslint/js/src/index.js?
    at new NodeError (node:internal/errors:405:5)
    at packageResolve (node:internal/modules/esm/resolve:890:9)
    at moduleResolve (node:internal/modules/esm/resolve:939:20)
    at defaultResolve (node:internal/modules/esm/resolve:1132:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}
bugs\vscode-eslint-test [main ≡ +0 ~1 -0 | +1 ~1 -0 !]>

IMO this is something the yarn people have to look into.

@davidkarlsson
Copy link

I can open a bug report in the Yarn repo for this but are you sure this is an problem with Yarn and not vscode-eslint or eslint? It looks like your repro works in node if you specify .pnp.loader.mjs as a loader which you always have to do with Yarn according to this comment: yarnpkg/berry#5241 (comment):

PS D:\vscode-eslint-test> $env:NODE_PATH
.yarn\sdks
PS D:\vscode-eslint-test> node -r ./.pnp.cjs --loader ./.pnp.loader.mjs
Welcome to Node.js v20.12.0.
Type ".help" for more information.
> .load bug.cjs
const library = require(`eslint`);

async function main() {
  const eslint = new (await library.loadESLint({ useFlatConfig: true }))();
  const report = await eslint.lintText(`var test = "hello";`);
  console.log(report);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 137,
  [Symbol(trigger_async_id_symbol)]: 134
}
> [
  {
    filePath: '<text>',
    messages: [],
    suppressedMessages: [],
    errorCount: 0,
    fatalErrorCount: 0,
    warningCount: 0,
    fixableErrorCount: 0,
    fixableWarningCount: 0,
    usedDeprecatedRules: [Getter]
  }
]

It also seems to work if you start node with yarn node without a loader argument because then the loader is registered automatically I think. I thought that this loader was injected in the node runtime by the vscode eslint sdk package that gets installed when you run the yarn dlx @yarnpkg/sdks vscode command so that it should be able to use ESM? From https://yarnpkg.com/getting-started/editor-sdks:

"The SDKs workaround that by generating indirection packages. When required, these indirection automatically setup the loader before forwarding the require calls to the real packages."

@dbaeumer
Copy link
Member

dbaeumer commented Apr 3, 2024

I thought that this loader was injected in the node runtime by the vscode eslint sdk package that gets installed when you run the yarn dlx @yarnpkg/sdks vscode command so that it should be able to use ESM?

Yes, and this is what is happening. By setting $env:NODE_PATH=".yarn/sdks" node is instructed to load node modules from .yarn/sdks which should inject the loader according to: https://yarnpkg.com/getting-started/editor-sdks

The yarn dlx @yarnpkg/sdks vscode sets the eslint.nodePath setting (see https://github.com/davidkarlsson/vscode-eslint-test/blob/main/.vscode/settings.json#L6) which the extension then passes on to node.

The extension itself doesn't know anything about yarn pnp.

@davidkarlsson
Copy link

Thanks @dbaeumer. I understand the issue better now. I also found another issue about more or less the same problem in #1602 where they fix the loader issue by registering it with the eslint.execArgv option. So I can get linting working with the mjs config file by setting the loader argument like this:

"eslint.execArgv": [
  "--loader=file:///d%3A/vscode-eslint-test/.pnp.loader.mjs"
],

But hardcoding the path there is not really a solution so I'm guessing all we can do is wait for either vscode to implement support for using variables in settings? Or do you think this could be fixed in Yarn somehow without having to use the node loader argument?

@dbaeumer
Copy link
Member

dbaeumer commented Apr 4, 2024

I am still the opinion that this should be addressed in Yarn / yarn dlx. This worked before and has only problems when trying to load mjs config files in ESLint. I don't know a lot about yarn pnp but my guess is that the loading works differently when doing cjs and mjs (they have two different loader files for this) and they don't expect eslint doing mjs load of a config file.

@dbaeumer
Copy link
Member

dbaeumer commented Apr 4, 2024

VS Code itself has an issue to support variables in settings which would be the right approach to avoid the hardcoded absolute path.

@dbaeumer
Copy link
Member

I created yarnpkg/berry#6219 to track the mjs load failure in yarn.

@ctjlewis
Copy link

ctjlewis commented Apr 20, 2024

This is not experimental you morons, it is the default output for the configuration file with eslint --init now. The current behavior of simply not recognizing the new config, without showing any kind of warning, is unjustifiable.

The old config files are now deprecated and are unrecognized on latest:

https://eslint.org/docs/latest/use/configure/configuration-files-deprecated

@skondrashov
Copy link

It does recognize it (you moron) as long as you set your working path correctly.

@ctjlewis
Copy link

I just copied an old .eslintrc and downgraded to 8.0.0 and things are working. This team's only job is to maintain this part of the software. Do better.

@skondrashov
Copy link

You're looking for the people over at eslint who changed how the config is looked up. "This team" is as far as I can tell one person and you certainly aren't paying them.

@konrazem
Copy link

I just copied an old .eslintrc and downgraded to 8.0.0 and things are working. This team's only job is to maintain this part of the software. Do better.

Thank you I didn't noticed I upgraded eslint by mistake. Go back from 9.1 to 8.31 solved this issue (or I think go step by step trough Migrate to v9.x)

@HatemMn
Copy link

HatemMn commented Apr 22, 2024

"eslint.experimental.useFlatConfig": true, This works for me but it seems to disable legacy config files. Would be nice if I could have both options on but I guess that's not possible?

For those who are still having the same problem, this solution has directly fixed it for me

@hanyufoodles
Copy link

I'm using the ESLint extension 3.0.5 and the issue still exists with whatever "eslint.experimental.useFlatConfig": true or "eslint.useFlatConfig": true.

It works fine with eslint.config.cjs in commonjs but it fails to find the module with mjs with yarn pnp. But running eslint on command line works with mjs file. The cause is either in the yarn editor sdk or in the vscode extension.

@dbaeumer
Copy link
Member

dbaeumer commented May 6, 2024

For yarn pnp please see: yarnpkg/berry#6219.

It basically doesn't work with the npm package of eslint in a non VS Code example either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
info-needed Issue requires more information from poster
Projects
None yet
Development

No branches or pull requests