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

Personal config (~/.eslintrc) doesn't load global-installed configs/parsers/plugins #11914

Assignees
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion core Relates to ESLint's core APIs and features enhancement This change enhances an existing feature of ESLint evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion

Comments

@matteodisabatino
Copy link

Tell us about your environment

  • ESLint Version: 6.0.1
  • Node Version: 12.4.0
  • npm Version: 6.9.0

What parser (default, Babel-ESLint, etc.) are you using? default

Please show your full configuration:

Configuration
{
  "env": {
    "browser": true,
    "commonjs": true,
    "es6": true,
    "node": true
  },
  "extends": [
    "standard"
  ],
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module"
  },
  "plugins": [
    "html",
    "css-in-js",
    "json"
  ],
  "rules": {
    "no-const-assign": "warn",
    "no-this-before-super": "warn",
    "no-undef": "warn",
    "no-unreachable": "warn",
    "no-unused-vars": "warn",
    "constructor-super": "warn",
    "valid-typeof": "warn"
  }
}

What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.

I updated eslint from version 5.16.0 to 6.0.1 and, since I did it, eslint failes to start and I always receive this error: 'Failed to load config "standard" to extend from eslint 6'.

What did you expect to happen?

I expected that all worked fine.

@matteodisabatino matteodisabatino added bug ESLint is working incorrectly triage An ESLint team member will look at this issue soon labels Jun 27, 2019
@mysticatea
Copy link
Member

Thank you for your report.

How do you run eslint?
As the migration guide says, we have changed the plugin resolution logic. Would you check if your problem is related to that or not?

@mysticatea mysticatea added core Relates to ESLint's core APIs and features evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion and removed triage An ESLint team member will look at this issue soon labels Jun 27, 2019
@matteodisabatino
Copy link
Author

Hi @mysticatea, thanks for you help. It seems you gotta reason because, as I read, "With ESLint v6, plugins should always be installed locally, even if ESLint was installed globally".
So there's no way to load global plugins? It's important to me...
Anyway I use eslint along with Visual Studio Code.

@mysticatea
Copy link
Member

I'm a VSCode user, too. If you installed eslint in project local, VSCode uses it. I'd like to recommend to use local installation with package.json because it allows us to share ESLint and plugins of the same versions with the development team, contributors, and CI system.

If you want to use global installation, use --resolve-plugins-relative-to option to specify the location of global-installed packages. I guess it's npm prefix -g.

In VSCode case, configure eslint.options.resolvePluginsRelativeTo option in your settings.json of VSCode.

@mysticatea mysticatea added question This issue asks a question about ESLint and removed bug ESLint is working incorrectly core Relates to ESLint's core APIs and features evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion labels Jun 27, 2019
@matteodisabatino
Copy link
Author

It seems not working, also via CLI.
If I run eslint --resolve-plugins-relative-to=/usr/local/lib/node_modules/ MY_FILE.js I receive this error:

Oops! Something went wrong! :(

ESLint: 6.0.1.

ESLint couldn't find the config "standard" to extend from. Please check that the name of the config is correct.

The config "standard" was referenced from the config file in "/Users/disa/.eslintrc.json".

If you still have problems, please stop by https://gitter.im/eslint/eslint to chat with the team.

The error persists also if I downgrade to version 6.0.0, but I'm sure that npm prefix is correct and the path of the file is correct too.

@mysticatea
Copy link
Member

Would you provide the result of eslint command with --debug option?

@matteodisabatino
Copy link
Author

matteodisabatino commented Jun 27, 2019

Oh sure, here the output:

  eslint:cli CLI args: [ '--debug', '--resolve-plugins-relative-to=/usr/local/lib/node_modules/', '/Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight/insight.controller.js' ] +0ms
  eslint:cli Running on files +6ms
  eslint:ignored-paths baseDir = "/Users/disa/Work/ISO e script" +0ms
  eslint:ignored-paths addPatternRelativeToCwd:
  eslint:ignored-paths   original = "/node_modules/*"
  eslint:ignored-paths   cooked   = "/node_modules/*" +1ms
  eslint:ignored-paths addPatternRelativeToCwd:
  eslint:ignored-paths   original = "/bower_components/*"
  eslint:ignored-paths   cooked   = "/bower_components/*" +0ms
  eslint:ignored-paths addPatternRelativeToCwd:
  eslint:ignored-paths   original = ".*"
  eslint:ignored-paths   cooked   = ".*" +0ms
  eslint:ignored-paths addPatternRelativeToCwd:
  eslint:ignored-paths   original = "!../"
  eslint:ignored-paths   cooked   = "!../" +0ms
  eslint:ignored-paths Looking for ignore file in /Users/disa/Work/ISO e script +0ms
  eslint:ignored-paths Could not find ignore file in cwd +1ms
  eslint:ignored-paths baseDir = "/Users/disa/Work/ISO e script" +0ms
  eslint:ignored-paths addPatternRelativeToCwd:
  eslint:ignored-paths   original = "/node_modules/*"
  eslint:ignored-paths   cooked   = "/node_modules/*" +0ms
  eslint:ignored-paths addPatternRelativeToCwd:
  eslint:ignored-paths   original = "/bower_components/*"
  eslint:ignored-paths   cooked   = "/bower_components/*" +0ms
  eslint:ignored-paths Looking for ignore file in /Users/disa/Work/ISO e script +1ms
  eslint:ignored-paths Could not find ignore file in cwd +0ms
  eslint:file-enumerator Start to iterate files: [ '/Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight/insight.controller.js' ] +0ms
  eslint:file-enumerator File: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight/insight.controller.js +2ms
  eslint:cascading-config-array-factory Load config files for /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight. +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils +1ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15. +1ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15 +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud +1ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio. +1ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131 +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches/Transmit. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches/Transmit +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library/Caches. +0ms
  eslint:config-array-factory Config file not found on /Users/disa/Library/Caches +1ms
  eslint:cascading-config-array-factory No cache found: /Users/disa/Library. +1ms
  eslint:config-array-factory Config file not found on /Users/disa/Library +0ms
  eslint:cascading-config-array-factory No cache found: /Users/disa. +0ms
  eslint:cascading-config-array-factory Stop traversing because of considered root. +0ms
  eslint:cascading-config-array-factory Loading the config file of the home directory. +0ms
  eslint:config-array-factory Loading JSON config file: /Users/disa/.eslintrc.json +1ms
  eslint:config-array-factory Config file found: /Users/disa/.eslintrc.json +1ms
  eslint:config-array-factory Loading {extends:"standard"} relative to /Users/disa/.eslintrc.json +15ms

Moreover if I run eslint --debug --config=~/.eslintrc.json --resolve-plugins-relative-to=/usr/local/lib/node_modules/ MY_FILE.js

I got this output:

  eslint:cli CLI args: [ '--debug', '--config=/Users/disa/.eslintrc.json', '--resolve-plugins-relative-to=/usr/local/lib/node_modules/', '/Users/disa/Library/Caches/Transmit/45D5F75B-1BED-4926-8990-CE2E61D2FEAF/35.204.250.131/home/apio/apio-cloud/public/boards/acea/15/utils/insight/insight.controller.js' ] +0ms
  eslint:cli Running on files +5ms
  eslint:config-array-factory Loading JSON config file: /Users/disa/.eslintrc.json +0ms
  eslint:config-array-factory Loading {extends:"standard"} relative to /Users/disa/.eslintrc.json +12ms

It let me think that all gone well but I always receive the error I said before.

@mysticatea
Copy link
Member

Thank you!

Hmm. Looks like that it failed to load eslint-config-standard rather than plugins.

Would you check what node -p "require.resolve('eslint-config-standard')" command on your home directory prints?

@matteodisabatino
Copy link
Author

I got this error:

internal/modules/cjs/loader.js:626
    throw err;
    ^

Error: Cannot find module 'eslint-config-standard'
Require stack:
- /Users/disa/[eval]
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:623:15)
    at Function.resolve (internal/modules/cjs/helpers.js:21:19)
    at [eval]:1:9
    at Script.runInThisContext (vm.js:123:20)
    at Object.runInThisContext (vm.js:313:38)
    at Object.<anonymous> ([eval]-wrapper:9:26)
    at Module._compile (internal/modules/cjs/loader.js:774:30)
    at evalScript (internal/process/execution.js:80:25)
    at internal/main/eval_string.js:23:3 {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/Users/disa/[eval]' ]
}

The error is the same if i type node -p "require.resolve('eslint-plugin-standard')"

@mysticatea
Copy link
Member

OK, thank you very much. I think I found what's happened.

More precisely, ESLint v6 resolves plugins relative to the end user’s project by default, and always resolves shareable configs and parsers relative to the location of the config file that imports them.

https://eslint.org/docs/user-guide/migrating-to-6.0.0#package-loading-simplification

This means that extends: "foo" works like require("eslint-config-foo") in the config file since ESLint 6.0.0. But this is different behavior from 5.x (global-installed ESLint had loaded from global-installed shareable configs).

If you installed that shareable config into your home directory, I guess it works.

@matteodisabatino
Copy link
Author

matteodisabatino commented Jun 27, 2019

So there's no other way than install the package where the config file is? Mmmm.... so bad.... I think I rollback to eslint 5. Any way thanks for your support :-)

@mysticatea
Copy link
Member

mysticatea commented Jun 27, 2019

I understand your position. I agree that the current personal config's behavior is not convenient.

@eslint/eslint-team ESLint uses ~/.eslintrc if there are no config files in the current project (it's called personal config). I think that it's convenient if ESLint finds also global-installed shareable configs and plugins when ESLint adopted the personal config. Thoughts?

(for a reference, lib/cli-engine/cascading-config-array-factory.js#L372-L384 is the code to load the personal config. I'm imaging to add a flag to that place to find also global-installed packages.)

@mysticatea mysticatea added core Relates to ESLint's core APIs and features enhancement This change enhances an existing feature of ESLint evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion and removed question This issue asks a question about ESLint labels Jun 27, 2019
@mysticatea mysticatea changed the title Problem with plugin standard Personal config (~/.eslintrc) doesn't load global-installed configs/parsers/plugins Jun 27, 2019
@mysticatea mysticatea self-assigned this Jun 27, 2019
@kaicataldo
Copy link
Member

I don’t think it’s a good idea to install and run ESLint globally and I’m a little bit hesitant about adding more options, because it encourages using this behavior.

Upgrading ESLint (even a semver-minor upgrade) can lead to more linting errors, and if someone had multiple projects on their machine they would potentially have to fix up errors in every project each time they upgrade.

If this same person collaborates with others (or runs automated testing), not defining the version in package.json can lead to mismatching results between runs.

That being said, I recognize that we already support this feature and I do think this change makes sense, given that we currently are supporting global installations.

@sgehrman
Copy link

I'm getting the same problem. will roll back eslint

@pascalduez
Copy link

Hi,

I have a similar use-case, that worked well until 6.x

We have a mono-repo, no lerna or fancy tools.
One base .eslintrc config at the repo root.

 {
   "root": true,
   "extends": "@company/config"
 }

All peerDependencies of that config are specified and installed per packages.
This way the packages can follow different upgrade times.
Also most packages don't require a special config, so they don't even have an .eslintrc.
If one package need some special tweaks, only adding an .eslintrc with the tweaks does the job.

I think that was a simple and effective pattern. Will this definitely be impossible now?

@wintercounter
Copy link

No, it doesn't make migration difficult. It makes it impossible for many of us. I know I can pass loader options. But again, it would require manual config from every user for every project then, which is unacceptable.

Imo ESLint should be able to resolve these things relative to the eslint module directory as well and that would solve this also.

Anyway, I'm starting to feel like I'll need to patch manually ESLint on file-system level to make this work. I really want to avoid this...

There would be so many solutions to resolve this issue:

  • Allow globals again.
  • Resolve configs/plugins relative to the loaded eslint module itself.
  • Add support for --resolve-configs-relative-to flag + add solution to pass CLI options in .eslintrc so 3rd party tools can automatically apply without extra config.
  • Allow configs to a be a file path (plugins can be, why not configs?)
  • Add option to define our own node_modules dir(s) to resolve from. (from rc file, not as a CLI flag).

I'm sure this thread will keep growing with reports from other users when they start to update their codebase.

@not-an-aardvark
Copy link
Member

As another option, you could create a wrapper script around ESLint that always invokes it with a specific set of options, to prevent users from always needing to supply additional CLI options.

As for your other suggestions: We're always open to looking at RFCs for behavior changes. It might be worth noting that several of the suggestions have been discussed in detail on other RFCs (e.g. here and here).

Speaking more broadly, I'm not sure it's realistic to expect that a tool's default settings will know how to handle every unusual custom setup. We try to provide reasonable default behaviors that work for the vast majority of users, and also allow for a great deal of customization (e.g. with CLI flags) that allows people to make things work with their own setup. But in order for that to work, one has to be willing to actually use the customization options.

@kurtextrem
Copy link

A short question: If we have --resolve-plugins-relative-to, why not also add --resolve-presets-relative-to? That would literally be just a copy & paste with minimal modifications and please everyone in this thread, future and existing issues all around the ecosystem.

@tonywoode
Copy link

tonywoode commented Sep 23, 2019

my 2cents: I can't upgrade eslint past v5, as ALE in Vim will report 'Failed to load config "standard"' - just as CLI does. I've read all issues here related to forcing users to stop using a global config, and I don't agree for reasons already cited above in this ticket. I see no option open to me atm than to slowly die on v5? That does not seem reasonable

@wintercounter
Copy link

I had enough of this and created the following package:
https://github.com/wintercounter/eslint-global-patch

It is a very unsafe and ugly workaround, it'll patch your ESLint installation. For my use case it works fine for all our projects.

@luzik
Copy link

luzik commented Nov 12, 2019

I believe that 5.x issues "design bug" affected less installations that 6.x design broke now. Standalone ESLint (outside node project) is now quite unusable. I have to change my editor --resolve-plugins-relative-to based on that if local project use node.js.

IMHO best solutions should be:

  1. add a way to include --resolve-configs-relative-to option in .eslintrc
  2. detect global .eslintrc usage and as a fallback to local plugins search user global npm installation

@wintercounter
Copy link

What it needs is that is working as any other module in the NodeJS ecosystem. ESLint cannot resolve modules relative to itself currently!

@matteodisabatino
Copy link
Author

I updated to eslint 6.7.2 but still I'm unable to use global modules. When i run eslint --resolve-plugins-relative-to /usr/local/lib MYFILE.js or eslint --resolve-plugins-relative-to /usr/local/lib//usr/local/lib/node_modules MYFILE.js I always receive this message:

Oops! Something went wrong! :(

ESLint: 6.7.2.

ESLint couldn't find the config "standard" to extend from. Please check that the name of the config is correct.

The config "standard" was referenced from the config file in "/Users/disa/.eslintrc.json".

If you still have problems, please stop by https://gitter.im/eslint/eslint to chat with the team.

standard and eslint-plugin-standardare installed as global and my .eslintrc.json is:

{
  "env": {
    "browser": true,
    "commonjs": true,
    "es6": true,
    "node": true
  },
  "extends": [
    "standard"
  ],
  "parser": "babel-eslint",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module"
  },
  "plugins": [
    "html",
    "css-in-js",
    "json"
  ],
  "rules": {
    "no-const-assign": "warn",
    "no-prototype-builtins": "off",
    "no-this-before-super": "warn",
    "no-undef": "warn",
    "no-unreachable": "warn",
    "no-unused-vars": "warn",
    "constructor-super": "warn",
    "valid-typeof": "warn"
  }
}

What am I wronging now?

@devsnek
Copy link

devsnek commented Dec 26, 2019

My solution:

// ~/.eslintrc.js

'use strict';
const Module = require('module');

const hacks = [
  'eslint-config-airbnb-base',
  'babel-eslint',
];

const ModuleFindPath = Module._findPath;
Module._findPath = (request, paths, isMain) => {
  const r = ModuleFindPath(request, paths, isMain);
  if (!r && hacks.includes(request)) {
    return require.resolve(`${process.env.HOME}/.npm-global/lib/node_modules/${request}`);
  }
  return r;
};

module.exports = {
  extends: 'airbnb-base',
  parser: 'babel-eslint',
  ... etc
};

this is so incredibly stupid. please add back global resolution in some capacity.

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