Eslint-plugin-import: eslint-module-utils 2.5.1 broken

Created on 11 Jan 2020  Â·  21Comments  Â·  Source: benmosher/eslint-plugin-import

Hey, when using eslint-module-utils 2.5.1, my eslint stops being able to resolve most imports. I receive lots of errors of this type:

1:1   error    Resolve error: unable to load resolver "node"    import/namespace

Pinning it at 2.5.0 makes all the errors go away. I won't ass lots of logs here as I assume it's something obvious. If it turns out to be more complicated, let me know and I'll give a full description of my setup. This was tested both with eslint 5.16.0 and 6.8.0.

utils

Most helpful comment

I can confirm that v2.5.2 fixes it for me! I was able to remove the explicit dependency on eslint-module-utils. Thank you for the wonderfully quick turnaround, @ljharb!

I'm sorry that I wasn't able to get you a repro repo. I'm glad you were able to find a solution despite that.

All 21 comments

What's your package.json and eslint config? Do you have an explicit dev dependency on eslint-import-resolver-node?

One of the changes in eslint-module-utils might cause dependencies that you previously were relying on being implicitly present to not be found.

What's your package.json and eslint config?

Let me start to say that it's really complicated and that I have been affected by the changes done to import in eslint 6.

To try to be a little more specific: I have a main app with a plugin system. When you start the app, it merges together a package.json file from the main app with package.json files from the plugins. I have created a django package for that specific purpose: https://github.com/fiduswriter/django-npm-mjs . For compilation, it copies the JavaScript files from each of the plugins and the main app into a folder (.transpile) and then uses webpack on them in there. So the package.json file resides in that .transpile folder and all the modules are inside of .trasnpile/node_modules/. Is that what you wnated to hear?

As for packages that are eslint related: Until before you released this 2.5.1, I specified these in package.json:

    "eslint": "^5.16.0",
    "eslint-plugin-import": "^2.18.2",
    "babel-eslint": "^10.0.3",

babel-eslint is used because I use dynamic imports and it looks like those are still not supported by regular eslint.

Now that this error occurred, I figured I could also try to find out whether the eslint6 module issue had been resolved, so now my package list looks like this (and it's working again):

    "eslint": "6.8.0",
    "eslint-global-patch": "1.0.4",
    "eslint-plugin-import": "2.20.0",
    "eslint-module-utils": "2.5.0",
    "babel-eslint": "10.0.3",

.eslintrc.js:

const path = require('path');

module.exports = {
    "env": {
        "browser": true,
        "es6": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:import/errors",
        "plugin:import/warnings"
    ],
    "settings": {
        "import/resolver": {
            "node": {
                "moduleDirectory": '.transpile/node_modules'
            },
            [path.resolve('testing/eslint-import-resolver')]: {}
        }
    },
    "parser": "babel-eslint",
    "parserOptions": {
      "sourceType": "module",
      "allowImportExportEverywhere": true,
      "ecmaFeatures": {
        "globalReturn": false,
      },
      "ecmaVersion": 2018,
      "sourceType": "module"
    },
    "rules": {
        "accessor-pairs": "error",
        "array-bracket-newline": "off",
        "array-bracket-spacing": [
            "error",
            "never"
        ],
        "array-callback-return": "off",
        "array-element-newline": "off",
        "arrow-body-style": "off",
        "arrow-parens": "off",
        "arrow-spacing": "off",
        "block-scoped-var": "error",
        "block-spacing": "off",
        "brace-style": "off",
        "callback-return": "error",
        "camelcase": "off",
        "capitalized-comments": "off",
        "class-methods-use-this": "off",
        "comma-dangle": "off",
        "comma-spacing": "warn",
        "comma-style": [
            "error",
            "last"
        ],
        "complexity": "off",
        "computed-property-spacing": [
            "error",
            "never"
        ],
        "consistent-return": "off",
        "consistent-this": "error",
        "curly": "off",
        "default-case": "off",
        "dot-location": [
            "error",
            "property"
        ],
        "dot-notation": "off",
        "eol-last": "off",
        "eqeqeq": "off",
        "func-call-spacing": "off",
        "func-name-matching": "error",
        "func-names": "off",
        "func-style": "off",
        "function-paren-newline": "off",
        "generator-star-spacing": "error",
        "global-require": "error",
        "guard-for-in": "off",
        "handle-callback-err": "off",
        "id-blacklist": "error",
        "id-length": "off",
        "id-match": "error",
        "implicit-arrow-linebreak": "off",
        "indent": "off",
        "indent-legacy": "off",
        "init-declarations": "off",
        "jsx-quotes": "error",
        "key-spacing": "off",
        "keyword-spacing": ["warn", { "before": true, "after": true }],
        "line-comment-position": "off",
        "linebreak-style": [
            "error",
            "unix"
        ],
        "lines-around-comment": "off",
        "lines-around-directive": "error",
        "lines-between-class-members": "off",
        "max-classes-per-file": "off",
        "max-depth": "off",
        "max-len": "off",
        "max-lines": "off",
        "max-lines-per-function": "off",
        "max-nested-callbacks": "error",
        "max-params": "off",
        "max-statements": "off",
        "max-statements-per-line": "off",
        "multiline-comment-style": "off",
        "multiline-ternary": "off",
        "new-parens": "error",
        "newline-after-var": "off",
        "newline-before-return": "off",
        "newline-per-chained-call": "off",
        "no-alert": "error",
        "no-array-constructor": "error",
        "no-async-promise-executor": "error",
        "no-await-in-loop": "error",
        "no-bitwise": "off",
        "no-buffer-constructor": "error",
        "no-caller": "error",
        "no-catch-shadow": "error",
        "no-cond-assign": [
            "error",
            "except-parens"
        ],
        "no-confusing-arrow": "off",
        "no-continue": "error",
        "no-div-regex": "error",
        "no-duplicate-imports": "off",
        "no-else-return": "off",
        "no-empty-function": "off",
        "no-eq-null": "error",
        "no-eval": "error",
        "no-extend-native": "error",
        "no-extra-bind": "error",
        "no-extra-label": "error",
        "no-extra-parens": "off",
        "no-floating-decimal": "error",
        "no-implicit-globals": "error",
        "no-implied-eval": "error",
        "no-inline-comments": "off",
        "no-invalid-this": "error",
        "no-iterator": "error",
        "no-label-var": "error",
        "no-labels": "error",
        "no-lone-blocks": "error",
        "no-lonely-if": "off",
        "no-loop-func": "off",
        "no-magic-numbers": "off",
        "no-misleading-character-class": "error",
        "no-mixed-operators": "off",
        "no-mixed-requires": "error",
        "no-multi-assign": "off",
        "no-multi-spaces": "off",
        "no-multi-str": "off",
        "no-multiple-empty-lines": "off",
        "no-native-reassign": "error",
        "no-negated-condition": "off",
        "no-negated-in-lhs": "error",
        "no-nested-ternary": "off",
        "no-new": "off",
        "no-new-func": "error",
        "no-new-object": "error",
        "no-new-require": "error",
        "no-new-wrappers": "error",
        "no-octal-escape": "error",
        "no-param-reassign": "off",
        "no-path-concat": "error",
        "no-plusplus": "off",
        "no-process-env": "off",
        "no-process-exit": "error",
        "no-proto": "error",
        "no-prototype-builtins": "off",
        "no-restricted-globals": "error",
        "no-restricted-imports": "error",
        "no-restricted-modules": "error",
        "no-restricted-properties": "error",
        "no-restricted-syntax": "error",
        "no-return-assign": "off",
        "no-return-await": "error",
        "no-script-url": "error",
        "no-self-assign": [
            "error",
            {
                "props": false
            }
        ],
        "no-self-compare": "error",
        "no-sequences": "error",
        "no-shadow": "off",
        "no-shadow-restricted-names": "error",
        "no-spaced-func": "off",
        "no-sync": "off",
        "no-tabs": [
            "error",
            {
                "allowIndentationTabs": true
            }
        ],
        "no-template-curly-in-string": "error",
        "no-ternary": "off",
        "no-throw-literal": "error",
        "no-trailing-spaces": "error",
        "no-undef-init": "error",
        "no-undefined": "off",
        "no-underscore-dangle": "error",
        "no-unmodified-loop-condition": "error",
        "no-unneeded-ternary": "off",
        "no-unused-expressions": "error",
        "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
        "no-use-before-define": "off",
        "no-useless-call": "error",
        "no-useless-catch": "off",
        "no-useless-computed-key": "error",
        "no-useless-concat": "error",
        "no-useless-constructor": "off",
        "no-useless-rename": "error",
        "no-useless-return": "off",
        "no-var": "error",
        "no-void": "error",
        "no-warning-comments": "off",
        "no-whitespace-before-property": "error",
        "no-with": "error",
        "nonblock-statement-body-position": [
            "error",
            "any"
        ],
        "object-curly-newline": "off",
        "object-curly-spacing": [
            "error",
            "never"
        ],
        "object-property-newline": "off",
        "object-shorthand": "off",
        "one-var": "off",
        "one-var-declaration-per-line": "off",
        "operator-assignment": "off",
        "operator-linebreak": "off",
        "padded-blocks": "off",
        "padding-line-between-statements": "error",
        "prefer-arrow-callback": "off",
        "prefer-const": "warn",
        "prefer-destructuring": "off",
        "prefer-numeric-literals": "error",
        "prefer-object-spread": "off",
        "prefer-promise-reject-errors": "off",
        "prefer-reflect": "off",
        "prefer-rest-params": "off",
        "prefer-spread": "error",
        "prefer-template": "off",
        "quote-props": "off",
        "quotes": "off",
        "radix": [
            "error",
            "as-needed"
        ],
        "require-atomic-updates": "error",
        "require-await": "error",
        "require-jsdoc": "off",
        "require-unicode-regexp": "off",
        "rest-spread-spacing": [
            "error",
            "never"
        ],
        "semi": ["error", "never"],
        "semi-spacing": "off",
        "semi-style": [
            "error",
            "last"
        ],
        "sort-keys": "off",
        "sort-vars": "off",
        "space-before-blocks": "warn",
        "space-before-function-paren": ["warn", "never"],
        "space-in-parens": ["warn", "never"],
        "space-infix-ops": "off",
        "space-unary-ops": "off",
        "spaced-comment": "off",
        "strict": "error",
        "switch-colon-spacing": "error",
        "symbol-description": "error",
        "template-curly-spacing": "off",
        "template-tag-spacing": [
            "error",
            "never"
        ],
        "unicode-bom": [
            "error",
            "never"
        ],
        "valid-jsdoc": "off",
        "vars-on-top": "error",
        "wrap-iife": "error",
        "wrap-regex": "off",
        "yield-star-spacing": "error",
        "yoda": "off"
    },
    "globals": {
        "gettext": false,
        "interpolate": false,
        "process": false
    }
};

One of the changes in eslint-module-utils might cause dependencies that you previously were relying on being implicitly present to not be found.

That sounds like this should have been a version 2.6.0, not 2.5.1. Doesn't it?

Is that what you wnated to hear?

This is coming off a bit defensive, i'm not sure why my question would have come off like an attack.

That sounds like this should have been a version 2.6.0, not 2.5.1. Doesn't it?

That'd be semver-minor, which is for adding new things; i think you were trying to suggest it'd be a breaking change which would make it v3.0.0 - but no, it's a bug to be able to require something that's not listed as a dependency.

Since you list the "node" resolver in settings, your package.json is broken unless you also list eslint-import-resolver-node. If you do list that, and try again, what happens?

This is coming off a bit defensive, i'm not sure why my question would have come off like an attack.

I think you are reading something into it that is not there. I was simply asking whether this was the kind of information you were interested in.

That'd be semver-minor, which is for adding new things; i think you were trying to suggest it'd be a breaking change which would make it v3.0.0 - but no, it's a bug to be able to require something that's not listed as a dependency.

I can see from your profile you are a teacher. You are right, 3.0.0 would probably have been even better. The point is that the release signifies a major change - so you should not just declare it a minor patch.

Since you list the "node" resolver in settings, your package.json is broken unless you also list eslint-import-resolver-node. If you do list that, and try again, what happens?

That's the first thing I tried as it seemed like the obvious fix. I tried to pin it to the version from before yesterday. But it didn't work. Then I went through every other eslint related package that I could find in package-lock.json until finally I arrived at this package and reported this bug. Are you sure eslint-import-resolver-node needs to be specified? According to package-lock.json, import-resolver-node is required by eslint-plugin-import which is why it's installed already even without being listed in package.json.

Right - that's exactly it. You're relying, implicitly, on npm's hoisting behavior that because eslint-plugin-import has it as a dep, that it will be available to your app. This is incorrect - if you require it (or if you reference it in a config) then you need to explicitly list it as a dependency.

@ljharb Let me repeat

  1. Specifying eslint-import-resolver-node in package.json did not solve the issue.
  2. Pinning eslint-module-utils to 2.5.0 did resolve the issue.
  3. eslint-import-resolver-node is installed already because it is a dependency of eslint-plugin-import 2.20.0.

I do understand that you have very concrete ideas about how everyone else should organize their work flow, but I ask you to please not break things like that again. My package.json was not broken until you broke it. Please stop doing that. Thank you.

And was that angry? I am starting to get a bit annoyed, but I wouldn't call it angry. I would just suggest you don't waste the time of other people like that.

I tried again. I removed the pinning of eslint-module-utils and instead pinned eslint-import-resolver-node to 0.3.3. It did not work.

Then I pinned eslint-import-resolver-node to 0.3.3 and eslint-module-utils to 2.5.1. Also this did not work.

The only thing that has worked so far is to pin eslint-module-utils to 2.5.0. Whether or not I mention either 0.3.2 or 0.3.3 of eslint-import-resolver-node in package.json seems to make no difference at all.

I am affected by this bug, as well, in a private project. I am using the webpack resolver, and am explicitly depending on [email protected] in my devDependencies. Snippet of .eslintrc.json:

"settings": {
  "import/resolver": {
    "webpack": {
      "config": "webpack.config.js"
    }   
  }   
}

For reasons, this project does not have a package-lock.json file, and instead I specify exact version numbers of our dependencies. Previously, eslint-module-utils was a transitive dependency because, as far as I know, I never refer to anything it offers directly. Today, the automated build broke, because it picked up the new version; [email protected] depends on eslint-module-utils@^2.4.1, and that floating dependency includes the newly-released 2.5.1.

The error I got was:

EslintPluginImportResolveError: unable to load resolver "webpack".

Explicitly depending on eslint-module-utils and pinning it to 2.5.0 fixed the build for me.

By the way, thank you @ljharb for maintaining this tool and responding on the weekend! And @johanneswilm, thank you for opening this issue - it helped me figure things out more quickly.

Yes, thanks for all your work @ljharb

Interesting; if it’s being explicitly depended on, then I’m not sure what the issue is. Ping @arcanis; I’ll have to revert #1591 if we can’t find a solution soon.

@jasonaowen would you have a minimal reproduction repository?

I don't have a minimal repository, but the full repo is open source and available here https://www.github.com/fiduswriter/fiduswriter.

Thanks @johanneswilm but that won't work. Your repository doesn't even have a package.json, and from what I understood you don't list the eslint-import-resolver-node dependency anyway.

What I'm most interested in is the case described by @jasonaowen, where an explicit loader wouldn't be resolvable. That would be incorrect and worth a fix.

Hey,
yes, as I tried to explain earlier, the package.json file is dynamically
being created by merging the contents of the individual package.json files
from the individual sub folders + those from any additional imported
plugins. It's mainly a python project. It's a really complex and
specialized setup and I don't expect you to study all parts of it. All I'm
asking is to please not try to limit where eslint related packages can be
imported packages from based on an assumption that all projects need to
have the same folder structure.

On Sun, Jan 12, 2020, 10:07 Maël Nison notifications@github.com wrote:

Thanks @johanneswilm https://github.com/johanneswilm but that won't
work. Your repository doesn't even have a package.json, and from what I
understood you don't list the eslint-import-resolver-node dependency anyway.

What I'm most interested in is the case described by @jasonaowen
https://github.com/jasonaowen, where an explicit loader wouldn't be
resolvable. That would be incorrect and worth a fix.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/benmosher/eslint-plugin-import/issues/1604?email_source=notifications&email_token=AAERMOHKC5W7A6QXFQ2KNG3Q5LMUXA5CNFSM4KFUFLI2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIWVGKA#issuecomment-573395752,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAERMOGIJP2CCRGIPIUCYS3Q5LMUXANCNFSM4KFUFLIQ
.

I'm currently in vacations with my family. Generally speaking, consider that if it takes maintainers more than 5 minutes to reproduce your issue, the fix will take significantly more time.

All I'm
asking is to please not try to limit where eslint related packages can be
imported packages from based on an assumption that all projects need to
have the same folder structure.

This isn't about enforcing folder structure - it's actually the very opposite. Your setup works because it has a very specific directory structure that relies on accidental quirks in the Node resolution algorithms. Because those quirks are the cause of many "doesn't work on my computer" problems, package managers are moving to enforce sound semantics by making sure that your packages can only access the dependencies they declare - regardless of your folder structure.

Anyway, I already submitted a PR that should solve your problem until the next major. I still advise you to fix your code, because it's broken regardless of the resolution of this issue.

And I'm on weekend with my family. But the introduction of a major change in a patch version release on your side forced me back to work yesterday.
If it really is currently broken for someone, then yes, add options to make it work for them. You can even make that the default for the next major release. Not adding a way to continue with the old folder structure structure (for example to locate parser packages with eslint6) seems like an oversight that will probably annoy many. So I would advise to please not do that. Our folder structure is not broken unless you change things in a way that give me no solution. Patching/forking eslint related packages or pinning them to old versions will then be the only way forward.

v2.5.2 of eslint-module-utils is released; hopefully that resolves the issue.

It solves it for me.

@ljharb Just to understand - what, according to your view of things, should be directly listed in my package.json file? I can remove the eslint-module-utils again and it continues to work without adding eslint-import-resolver-node. But you think I should add eslint-import-resolver-node and leave eslint-module-utils out. Is that correctly understood?

@johanneswilm You should definitely leave eslint-module-utils out.

In general, I'd say that you should explicitly have eslint-import-resolver-node included - however, it seems that the design and usage pattern here has always been that that resolver is implicitly available, so for now I think it's fine to leave it out too.

I can confirm that v2.5.2 fixes it for me! I was able to remove the explicit dependency on eslint-module-utils. Thank you for the wonderfully quick turnaround, @ljharb!

I'm sorry that I wasn't able to get you a repro repo. I'm glad you were able to find a solution despite that.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

segmentationfaulter picture segmentationfaulter  Â·  4Comments

silvenon picture silvenon  Â·  3Comments

xiaodi0003 picture xiaodi0003  Â·  3Comments

ljharb picture ljharb  Â·  3Comments

gaearon picture gaearon  Â·  3Comments