npm / cli

the package manager for JavaScript
https://docs.npmjs.com/cli/
Other
8.36k stars 3.09k forks source link

npm install infinite recursion on building tree while using `--force` with certain package combinations #4488

Open rogerfar opened 2 years ago

rogerfar commented 2 years ago

Is there an existing issue for this?

This issue exists in the latest npm version

Current Behavior

The following infinite recursion occurs when doing npm install:

200001 silly placeDep ROOT @ngtools/webpack@13.2.5 OK for: @angular-devkit/build-angular@13.2.5 want: 13.2.5
200002 silly placeDep ROOT typescript@4.5.5 REPLACE for: @ngtools/webpack@13.2.5 want: >=4.4.3 <4.6
200003 timing idealTree:node_modules/@angular-devkit/build-angular Completed in 1ms
200004 silly placeDep ROOT typescript@ REPLACE for: client@1.0.0 want: 4.6.0
200005 timing idealTree:#root Completed in 1ms
200006 silly placeDep ROOT @ngtools/webpack@13.2.5 OK for: @angular-devkit/build-angular@13.2.5 want: 13.2.5
200007 silly placeDep ROOT typescript@4.5.5 REPLACE for: @ngtools/webpack@13.2.5 want: >=4.4.3 <4.6
200008 timing idealTree:node_modules/@angular-devkit/build-angular Completed in 11ms
200009 silly placeDep ROOT typescript@ REPLACE for: client@1.0.0 want: 4.6.0
200010 timing idealTree:#root Completed in 0ms
200011 silly placeDep ROOT @ngtools/webpack@13.2.5 OK for: @angular-devkit/build-angular@13.2.5 want: 13.2.5
200012 silly placeDep ROOT typescript@4.5.5 REPLACE for: @ngtools/webpack@13.2.5 want: >=4.4.3 <4.6
200013 timing idealTree:node_modules/@angular-devkit/build-angular Completed in 1ms
200014 silly placeDep ROOT typescript@ REPLACE for: client@1.0.0 want: 4.6.0
200015 timing idealTree:#root Completed in 0ms
200016 silly placeDep ROOT @ngtools/webpack@13.2.5 OK for: @angular-devkit/build-angular@13.2.5 want: 13.2.5
200017 silly placeDep ROOT typescript@4.5.5 REPLACE for: @ngtools/webpack@13.2.5 want: >=4.4.3 <4.6
200018 timing idealTree:node_modules/@angular-devkit/build-angular Completed in 1ms
200019 silly placeDep ROOT typescript@ REPLACE for: client@1.0.0 want: 4.6.0
200020 timing idealTree:#root Completed in 0ms
200021 silly placeDep ROOT @ngtools/webpack@13.2.5 OK for: @angular-devkit/build-angular@13.2.5 want: 13.2.5
200022 silly placeDep ROOT typescript@4.5.5 REPLACE for: @ngtools/webpack@13.2.5 want: >=4.4.3 <4.6
200023 timing idealTree:node_modules/@angular-devkit/build-angular Completed in 1ms
200024 silly placeDep ROOT typescript@ REPLACE for: client@1.0.0 want: 4.6.0
200025 timing idealTree:#root Completed in 0ms
200026 silly placeDep ROOT @ngtools/webpack@13.2.5 OK for: @angular-devkit/build-angular@13.2.5 want: 13.2.5
200027 silly placeDep ROOT typescript@4.5.5 REPLACE for: @ngtools/webpack@13.2.5 want: >=4.4.3 <4.6
200028 timing idealTree:node_modules/@angular-devkit/build-angular Completed in 2ms
200029 silly placeDep ROOT typescript@ REPLACE for: client@1.0.0 want: 4.6.0

Expected Behavior

No response

Steps To Reproduce

{
  "name": "client",
  "version": "1.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "update": "ng update --allow-dirty --force @angular/cli @angular/core @clr/angular @clr/icons rxjs"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^13.2.4",
    "@angular/common": "^13.2.4",
    "@angular/compiler": "^13.2.4",
    "@angular/core": "^13.2.4",
    "@angular/forms": "^13.2.4",
    "@angular/platform-browser": "^13.2.4",
    "@angular/platform-browser-dynamic": "^13.2.4",
    "@angular/router": "^13.2.4",
    "@cds/core": "5.6.4",
    "@clr/angular": "13.0.2",
    "@clr/icons": "13.0.2",
    "@clr/ui": "13.0.2",
    "@microsoft/signalr": "^6.0.2",
    "@webcomponents/webcomponentsjs": "^2.6.0",
    "clone": "^2.1.2",
    "core-js": "^3.21.1",
    "curray": "1.0.8",
    "file-saver": "^2.0.5",
    "guid-typescript": "^1.0.9",
    "highcharts": "^9.3.3",
    "highcharts-angular": "^3.0.0",
    "highlight.js": "^11.4.0",
    "json-formatter-js": "^2.3.4",
    "moment": "^2.29.1",
    "monaco-editor": "^0.32.1",
    "ngx-cookie-service": "^13.1.2",
    "ngx-highlightjs": "6.1.1",
    "ngx-monaco-editor": "^12.0.0",
    "rxjs": "^7.5.4",
    "tslib": "^2.3.1",
    "tslint-angular": "^3.0.3",
    "tslint-config-prettier": "^1.18.0",
    "vkbeautify": "^0.99.3",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^13.2.5",
    "@angular/cli": "~13.2.5",
    "@angular/compiler-cli": "^13.2.4",
    "@angular/language-service": "^13.2.4",
    "@types/file-saver": "^2.0.5",
    "@types/jasmine": "~3.10.3",
    "@types/jasminewd2": "~2.0.10",
    "@types/node": "^17.0.21",
    "@types/uuid": "^8.3.4",
    "codelyzer": "^6.0.2",
    "husky": "^7.0.4",
    "jasmine-core": "~4.0.1",
    "jasmine-spec-reporter": "~7.0.0",
    "karma": "~6.3.17",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.3",
    "karma-jasmine": "~4.0.1",
    "karma-jasmine-html-reporter": "^1.7.0",
    "prettier": "^2.5.1",
    "pretty-quick": "^3.1.3",
    "protractor": "~7.0.0",
    "ts-node": "~10.6.0",
    "tslint": "~6.1.3",
    "typescript": "4.6.0"
  }
}

Environment

nlf commented 2 years ago

this one is interesting, so i'm going to walk through it step by step.

if i run npm i i get

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: client@1.0.0
npm ERR! Found: @angular/common@13.2.5
npm ERR! node_modules/@angular/common
npm ERR!   @angular/common@"^13.2.4" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @angular/common@"^12.0.0" from ngx-monaco-editor@12.0.0
npm ERR! node_modules/ngx-monaco-editor
npm ERR!   ngx-monaco-editor@"^12.0.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

which is telling us that the peer dependency for @angular/common specified by ngx-monaco-editor conflicts with the version of @angular/common specified in the package.json. we can get around this by using either the --legacy-peer-deps flag, or the --force flag.

the result of npm i --legacy-peer-deps is:

npm ERR! code ETARGET
npm ERR! notarget No matching version found for typescript@4.6.0.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn't exist.

this happens because your root package is depending on typescript at the specific version 4.6.0, which appears it was never published as only prerelease versions of 4.6.0 exist in the npm registry. if i change the root requirement for typescript to either 4.5.5 or 4.6.2 which are published versions available in the registry, then npm i --legacy-peer-deps finishes successfully.

the other suggestion offered in the error message above is to use --force, which is what triggers this issue because we skip our normal dependency resolution and try to force typescript@4.5.5 instead of the 4.6.0 specified in the package.json. however, it does appear we have a bug in how we handle dependencies that we've overwritten due to the --force flag causing this infinite loop.

the fix for your specific use case is to change your typescript dependency to a version available in the npm registry and to run npm install --legacy-peer-deps. npm i --force also works correctly after correcting the typescript requirement, though i would lean heavily toward using --legacy-peer-deps and avoiding --force as much as possible due to other protections it disables.

i'm going to leave this issue open to track the work of fixing the infinite loop when using --force while specifying a package version that doesn't exist.