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

ESlint plugins are conflicted each other migrating to pnpm #4619

Closed
baeharam opened this issue Apr 25, 2022 · 17 comments
Closed

ESlint plugins are conflicted each other migrating to pnpm #4619

baeharam opened this issue Apr 25, 2022 · 17 comments

Comments

@baeharam
Copy link

pnpm version: 6.32.9

Code to reproduce the issue:

I tried to reproduce error using CRA, but couldn't figure out exact condition 😢

Expected behavior:

ESLint plugins don't conflict

Actual behavior:

Plugin "@typescript-eslint" was conflicted between ".eslintrc.json" and ".eslintrc.json » eslint-config-react-app#overrides[0]".
ERROR in Plugin "@typescript-eslint" was conflicted between ".eslintrc.json" and ".eslintrc.json » eslint-config-react-app#overrides[0]".

The reason why I posted this issue on pnpm is that eslint didn't conflict when we were using npm. This error was occurred migrating from npm to pnpm. I tried lots of experiments.

  • Remove node_modules and install from scratch -> Failed
  • Remove all eslint packages and re-install from scratch -> Failed

From this situation, I cannot no longer guess what is the real problem? I think installation mechanism of pnpm is related to this issue. Is there other reason that you think? Thanks for your reading.

@jasongodev
Copy link

Just to be sure, can you try a fresh pnpm install in your current project directory, BUT put a .npmrc file with node-linker=hoisted as the setting? Just to be sure it's not about node module resolution issues?

In my experience, it solves half of my problems with pnpm.

@baeharam
Copy link
Author

@jasongodev I tried your solution.

  • Put node-linker = hoisted to .npmrc file.
  • Remove node_modules.
  • Install using pnpm i from scratch.

Failed and other errors were occurred 😢

@jasongodev
Copy link

Will it be possible for you to share your project so we can test? Remove all business critical code, api keys, and personal identifiers.

@baeharam
Copy link
Author

@jasongodev As I said in description, I couldn't figure out exact cause of this issue. So, I cannot reproduce this situation. Is there any guess you think?

@brentertz
Copy link

@baeharam I faced a similar issue, after upgrading to pnpm 7. I resolved it by adding eslint and eslint-config-react-app to devDependencies as described here.

@atablash
Copy link

I had a similar issue:

[Info  - 11:59:46 AM] ESLint server is starting
[Info  - 11:59:46 AM] ESLint server running in node v16.13.0
[Info  - 11:59:46 AM] ESLint server is running.
[Info  - 11:59:47 AM] ESLint library loaded from: /home/atablash/voltiso/node_modules/.pnpm/eslint@8.18.0/node_modules/eslint/lib/api.js
[Error - 11:59:48 AM] ESLint stack trace:
[Error - 11:59:48 AM] Error: Plugin "prettier" was conflicted between ".eslintrc.js" and ".eslintrc.js » plugin:github/recommended".
    at mergePlugins (/home/atablash/voltiso/node_modules/.pnpm/@eslint+eslintrc@1.3.0/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:598:19)
    at createConfig (/home/atablash/voltiso/node_modules/.pnpm/@eslint+eslintrc@1.3.0/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:701:9)
    at ConfigArray.extractConfig (/home/atablash/voltiso/node_modules/.pnpm/@eslint+eslintrc@1.3.0/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:877:33)
    at CLIEngine.isPathIgnored (/home/atablash/voltiso/node_modules/.pnpm/eslint@8.18.0/node_modules/eslint/lib/cli-engine/cli-engine.js:990:18)
    at CLIEngine.executeOnText (/home/atablash/voltiso/node_modules/.pnpm/eslint@8.18.0/node_modules/eslint/lib/cli-engine/cli-engine.js:899:38)
    at ESLint.lintText (/home/atablash/voltiso/node_modules/.pnpm/eslint@8.18.0/node_modules/eslint/lib/eslint/eslint.js:592:23)
    at /home/atablash/.vscode-server/extensions/dbaeumer.vscode-eslint-2.2.2/server/out/eslintServer.js:1:180347
    at Ce (/home/atablash/.vscode-server/extensions/dbaeumer.vscode-eslint-2.2.2/server/out/eslintServer.js:1:186295)
    at /home/atablash/.vscode-server/extensions/dbaeumer.vscode-eslint-2.2.2/server/out/eslintServer.js:1:180305
    at /home/atablash/.vscode-server/extensions/dbaeumer.vscode-eslint-2.2.2/server/out/eslintServer.js:1:181582

The problem is I'm using eslint configs that declare plugins as regular non-peer dependencies.

  • BTW. I do it the same way with my config package, because currently PNPM's auto-install-peers does not seem to work for me like I want - I don't want to manually install all peer dependencies of the config package in my projects

Using PNPM's override field in package.json, I force a single version of the problematic package - e.g. esling-plugin-prettier in my case:

	"pnpm": {
		"overrides": {
			"@typescript-eslint/eslint-plugin": "latest",
			"eslint": "latest",
			"prettier": "latest",
			"eslint-plugin-jsonc": "latest",
			"eslint-plugin-unicorn": "latest"
		},

The problem still persisted, because eslint uses file path to figure out if the plugin is the same package. I think it didn't even resolve symlinks using fs.realpath.

So I made a patch-package patch to fix this. But resolving symlinks still didn't help: even though the eslint-plugin-prettier was the exact same version and hardlinked to the same place on disk, PNPM can put the same package in different "node_modules contexts" depending on the set of dependencies it's used together with.

So the final patch checks is the file is hardlinked to the same place on disk... not sure if this is 100% correct, because of these different "node_modules contexts" but it works for me.

The patch generated using @milahu/patch-package-with-pnpm-support:

# generated by patch-package 6.4.10
#
# command:
#   npx patch-package @eslint/eslintrc
#
# declared package:
#   @eslint/eslintrc: 1.3.0 || *
#
diff --git a/node_modules/@eslint/eslintrc/dist/eslintrc.cjs b/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
index 8b07ba1..31c2c80 100644
--- a/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
+++ b/node_modules/@eslint/eslintrc/dist/eslintrc.cjs
@@ -563,12 +563,24 @@ class PluginConflictError extends Error {
      * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
      */
     constructor(pluginId, plugins) {
-        super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
+        super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}. Files not linking to the same place on disk: ${plugins.map(p => p.filePath).join(' and ')}`);
         this.messageTemplate = "plugin-conflict";
         this.messageData = { pluginId, plugins };
     }
 }
 
+function isSameFile(pathA, pathB) {
+  try {
+    const statA = fs.statSync(pathA)
+    const statB = fs.statSync(pathB)
+    if(typeof statA?.ino !== 'number' || typeof statB?.ino !== 'number') return false
+    else return statA.ino === statB.ino
+  } catch(error) {
+    console.error(error)
+    return false
+  }
+}
+
 /**
  * Merge plugins.
  * `target`'s definition is prior to `source`'s.
@@ -594,7 +606,7 @@ function mergePlugins(target, source) {
                 throw sourceValue.error;
             }
             target[key] = sourceValue;
-        } else if (sourceValue.filePath !== targetValue.filePath) {
+        } else if (!isSameFile(sourceValue.filePath, targetValue.filePath)) {
             throw new PluginConflictError(key, [
                 {
                     filePath: targetValue.filePath,

I'm not sure about performance of the synchronous fs.statSync calls - but it seems ok for my use case. 😎

Also, I'm using Ubuntu WSL - I'm not exactly sure how cross-platform node's stat implemetation is - is it "polyfilled" for Windows or not.

@rdsedmundo
Copy link

Also facing this, even though I was forcing a version through pnpm.overrides on package.jsn, the paths to the final file were diffing, thus ESLint was throwing:

Files not linking to the same place on disk: 
/Users/work/redacted/redacted/node_modules/.pnpm/eslint-plugin-react@7.30.0_eslint@8.23.0/node_modules/eslint-plugin-react/index.js
/Users/work/redacted/redacted/node_modules/.pnpm/eslint-plugin-react@7.30.0_eslint@8.10.0/node_modules/eslint-plugin-react/index.js

There was a difference on the ESLint version on the folder structure that pnpm uses to name the folder.

@tyteen4a03
Copy link

+1 - same issue here.

@ggascoigne
Copy link

Same issue here, you can reproduce it on https://github.com/ggascoigne/festive-beverage/tree/d6f0e76fa5208dd923351fc3ad50f7ca72c81378. Clone it, pnpm install && pnpm lint - boom.

Oops! Something went wrong! :(

ESLint: 8.28.0

ESLint couldn't determine the plugin "import" uniquely.

- /Users/ggp/dev/git/fb.test/node_modules/.pnpm/eslint-plugin-import@2.26.0_a7dttoi4ai57yudycjcunoobfu/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.js » @ggascoigne/eslint-config/ts » ./index.js » eslint-config-react-app")
- /Users/ggp/dev/git/fb.test/node_modules/.pnpm/eslint-plugin-import@2.26.0_vfrilbydaxalswvos6uuh4sxs4/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.js » @ggascoigne/eslint-config/ts » ./index.js » ./base.js » eslint-config-airbnb-base » /Users/ggp/dev/git/fb.test/node_modules/.pnpm/eslint-config-airbnb-base@15.0.0_ktrec6dplf4now6nlbc6d67jee/node_modules/eslint-config-airbnb-base/rules/imports.js")

Please remove the "plugins" setting from either config or remove either plugin installation.

@dormammun
Copy link

Is there some workaround? Seems pnpm adds some hash to the packages and when eslint check packages they are not equal.

Error: Plugin "import" was conflicted between "package.json » @packages/eslint-config-hub/.remix.js » ./.react.js » ./.base.js » plugin:import/recommended" and "package.json » @packages/eslint-config-hub/.remix.js » ./.react.js » ./.base.js » plugin:github/recommended".

If you debug where error is happens: node_modules/.pnpm/@eslint+eslintrc@1.4.1/node_modules/@eslint/eslintrc/dist/eslintrc.cjs

else if (sourceValue.filePath !== targetValue.filePath) {
            console.log(targetValue.filePath)
            console.log(sourceValue.filePath)
            throw new PluginConflictError(key, [
                {
                    filePath: targetValue.filePath,
                    importerName: targetValue.importerName
                },
                {
                    filePath: sourceValue.filePath,
                    importerName: sourceValue.importerName
                }
            ]);
        }
    }

You will get this:

/Users/dormammun/code/random-video-chat/hub/node_modules/.pnpm/eslint-plugin-import@2.26.0/node_modules/eslint-plugin-import/lib/index.js

/Users/dormammun/code/random-video-chat/hub/node_modules/.pnpm/eslint-plugin-import@2.26.0_k6edyionkpwtvb5fzwjupgro4y/node_modules/eslint-plugin-import/lib/index.js

eslint-plugin-import@2.26.0 vs eslint-plugin-import@2.26.0_k6edyionkpwtvb5fzwjupgro4y

@dormammun
Copy link

Fixed with:
.npmrc

auto-install-peers = true

@Amit0617
Copy link

Amit0617 commented Mar 1, 2023

Fixed with: .npmrc

auto-install-peers = true

May you explain what you did there? Did you also removed node_modules and did pnpm install?

Edit: Yes! It solved issue for me too. My warning was little different though.

Creating an optimized production build...
Failed to compile.

[eslint] Plugin "react" was conflicted between "package.json » eslint-config-react-app » /home/amit/codelib/web/iris/node_modules/eslint-config-react-app/base.js" and "BaseConfig » /home/amit/codelib/web/iris/node_modules/.pnpm/eslint-config-react-app@7.0.1_eslint@8.35.0+jest@27.5.1/node_modules/eslint-config-react-app/base.js".

This was occuring during pnpm start too but website was rendering even with the warning.

@nnecec
Copy link

nnecec commented Mar 2, 2023

same issue

Oops! Something went wrong! :(

ESLint: 8.35.0

ESLint couldn't determine the plugin "import" uniquely.

- /node_modules/.pnpm/eslint-plugin-import@2.27.5_z4t62rwba3aha3c5ltpvvca4q4/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.js » @remix-run/eslint-config")
- /node_modules/.pnpm/eslint-plugin-import@2.27.5_ajyizmi44oc3hrc35l6ndh7p4e/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.js » @nnecec/eslint-config/react-universal » ./react » ./typescript » ./base.js » plugin:import/recommended")

Please remove the "plugins" setting from either config or remove either plugin installation.

@ggascoigne
Copy link

I'll add that I've been using the patch that @atablash provided (updated to the latest @eslint/eslintrc@2.0.1), and find that it's still required regardless of how I configure pnpm.

My pnpm flags are:

auto-install-peers=true
dedupe-peer-dependents=true
use-lockfile-v6=true
save-workspace-protocol=rolling
resolve-peers-from-workspace-root=true

@nnecec
Copy link

nnecec commented Apr 3, 2023

same issue

Oops! Something went wrong! :(

ESLint: 8.35.0

ESLint couldn't determine the plugin "import" uniquely.

- /node_modules/.pnpm/eslint-plugin-import@2.27.5_z4t62rwba3aha3c5ltpvvca4q4/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.js » @remix-run/eslint-config")
- /node_modules/.pnpm/eslint-plugin-import@2.27.5_ajyizmi44oc3hrc35l6ndh7p4e/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.js » @nnecec/eslint-config/react-universal » ./react » ./typescript » ./base.js » plugin:import/recommended")

Please remove the "plugins" setting from either config or remove either plugin installation.

auto fixed when I update pnpm to v8.0.0 😂

@baeharam
Copy link
Author

It's already been year I posted this issue and I think this issue could be solved by updating recent version of pnpm 😄

@christopher-francisco
Copy link

@baeharam "recent"as in latest 7, or 8?

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

No branches or pull requests