ESLint couldn't determine the plugin uniquely.
See original GitHub issueI’m trying to upgrade to eslint@7.1.0 but some breaking changes in the plugin resolution seems to get in the way. I’m using a monorepo with yarn workspaces and the noHoist setting. My current tree looks like this
package.json
.eslintrc
node_modules/
packages/
app/
.eslintrc
package.json
node_modules/
api/
.eslintrc
package.json
node_modules/
but when I run yarn workspace app lint
$ eslint src/**.ts*
Oops! Something went wrong! :(
ESLint: 7.0.0
ESLint couldn't determine the plugin "prettier" uniquely.
- /myproject/packages/app/node_modules/eslint-plugin-prettier/eslint-plugin-prettier.js (loaded in ".eslintrc » ../../.eslintrc")
- /myproject/node_modules/eslint-plugin-prettier/eslint-plugin-prettier.js (loaded in "../../.eslintrc")
Please remove the "plugins" setting from either config or remove either plugin installation.
My packages .eslintrc configuration files are just
{
"extends": ["../../.eslintrc"]
}
which are supposed to help us load specific plugins per package (i.e. eslint-plugin-react for app, not for api)
Any idea where to go from here?
I posted my issue on Gitter and someone suggested to use --resolve-plugins-relative-to
but so far, eslint --resolve-plugins-relative-to ./packages/app src/**.ts*
and eslint --resolve-plugins-relative-to ./packages/app src/**.ts*
still look in the ROOT node_modules
. Am I missing something?
Bonus question for my curiosity: why eslint@7 wants uniqueness so badly?
Tell us about your environment
- yarn v1.22.4
- working ESLint:
6.8.0
./node_modules/.bin/eslint --env-info
Environment Info:
Node version: v14.3.0
npm version: v6.14.4
Local ESLint version: Not found
Global ESLint version: Not found
- not-working ESLint:
7.0.0
&7.1.0
Please show your full configuration:
Root .eslintrc
{
"env": {
"browser": true,
"es6": true
},
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": ["./tsconfig.json"],
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"settings": {
"react": {
"version": "detect"
}
},
"plugins": [
"prettier",
"jest",
"@typescript-eslint",
"import",
"react",
"react-hooks",
"functional"
],
"extends": [
"eslint:recommended",
"prettier",
"plugin:jest/recommended",
"plugin:prettier/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:functional/external-recommended",
"plugin:functional/recommended"
],
"rules": {
"prettier/prettier": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/no-this-in-sfc": "error",
"react/prefer-stateless-function": "error",
"react/jsx-pascal-case": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/no-dynamic-delete": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-arguments": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/prefer-as-const": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-optional-chain": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/restrict-template-expressions": "error",
"@typescript-eslint/strict-boolean-expressions": "error",
"@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/default-param-last": "error",
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-dupe-class-members": "error",
"@typescript-eslint/no-empty-function": "error",
"@typescript-eslint/no-use-before-define": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/return-await": "error",
"import/first": "error",
"import/order": [
"error",
{
"groups": [
"index",
"sibling",
"parent",
"internal",
"external",
"builtin"
],
"newlines-between": "never",
"alphabetize": {
"order": "asc"
}
}
],
"import/no-default-export": "error",
"import/no-unused-modules": ["warn", { "unusedExports": true }],
"functional/no-expression-statement": [
"error",
{
// Ignored for Jest usage: "test" & "expect"
// Ingored for React usage: "ReactDOM", "set*" (hooks)
"ignorePattern": ["test", "expect", "ReactDOM", "set*"]
}
],
"functional/functional-parameters": "off" // in React & Jest, too many things work without parameters
}
}
Children .eslintrc
``` { "extends": ["../../.eslintrc"] } ```Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:7 (2 by maintainers)
Top GitHub Comments
@MaximeBernard ESLint loads all config files from the ancestor directories of lint target files. Then, ESLint 7.x loads plugins from the location of each config file which has the
plugins
field. (On the other hand, ESLint 6.x loads all plugins from the current working directory.)In your case, I guess it’s solved if you add
root: true
into your config file. It stops ESLint loading other config files from ancestor directories than the config file.(currently, it loads
.eslintrc
twice becausepackages/*/.eslintrc
extends it and ESLint loads config files from ancestor directories. It looks extra a bit, androot:true
will improve it.)Similar issue. My app/ creates scaffolding (e.g. downstream) as part of an integration test.
adding
--resolve-plugins-relative-to .
to the downstream.eslintrc
addressed the issue