Search code examples
node.jspowershellnpmgit-bashwindows-terminal

npm is not working in the Windows Terminal


I have currently installed the latest NodeJS (v19.9.0) through winget. Using it through Git Bash works just fine, however if I try using it through PowerShell or Windows Terminal the node command works just fine, but trying to use npm will result in the following error:

node:internal/modules/cjs/loader:1093
  throw err;
  ^

Error: Cannot find module 'C:\Program Files\nodejs\node_modules\npm\bin\node_modules\npm\bin\npm-cli.js'
    at Module._resolveFilename (node:internal/modules/cjs/loader:1090:15)
    at Module._load (node:internal/modules/cjs/loader:934:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Node.js v19.9.0
node:internal/modules/cjs/loader:1093
  throw err;
  ^

Error: Cannot find module 'C:\Program Files\nodejs\node_modules\npm\bin\node_modules\npm\bin\npm-cli.js'
    at Module._resolveFilename (node:internal/modules/cjs/loader:1090:15)
    at Module._load (node:internal/modules/cjs/loader:934:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Node.js v19.9.0

I have already tried reinstalling Node through the official website downloadable and also reinstall Windows Terminal/Powershell. I also deleted temporary files and made sure that the Path Environmental Variable is configured correctly.


Solution

  • tl;dr

    Remove the following directory from your persistent Path environment-variable definition via the registry (run sysdm.cpl, go to the Advanced tab, and click on Environment variables...) or otherwise ensure that it doesn't end up as part of $env:Path in your PowerShell sessions:

    C:\Program Files\nodejs\node_modules\npm\bin
    

    Only C:\Program Files\nodejs should be in $env:Path, which contains the proper CLI entry point, npm.cmd, alongside the Node.JS executable, node.exex`


    There are multiple npm.cmd files in the subtree of C:\Program Files\nodejs, and they all look for either npm-cli.js or npm.js in a location relative to their own.

    C:\Program Files\nodejs\node.cmd and C:\Program Files\nodejs\node_modules\npm\bin\node.cmd are identical and use the following path to find the actual .js entry point, npm-cli.js, which is launched via node.exe:

    SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js"
    

    That is, npm-cli.js is looked for in subfolder .\node_modules\npm\bin of the same directory in which npm.cmd is located.

    This only works for C:\Program Files\nodejs\node.cmd, not for C:\Program Files\nodejs\node_modules\npm\bin\node.cmd, which ends up looking for
    C:\Program Files\nodejs\node_modules\npm\bin\node_modules\npm\bin\npm-cli.js - note the doubled node_modules\npm\bin part - which doesn't exist.

    In your case, the mistaken C:\Program Files\nodejs\node_modules\npm\bin entry in $env:Path apparently comes before the proper C:\Program Files\nodejs entry, and therefore the wrong npm.cmd batch file executes when you invoke a command with just npm (or npm.cmd).

    Removing the mistaken entry should fix that problem.

    In general, if the wrong executable is being invoked when you use a mere file name such as npm, use Get-Command with the -All switch to show all such executables, in order of precedence: the one listed first is the effective one; e.g.:

    # Print the full paths of all "npm" executables located in directories
    # listed in $env:Path; the first one "wins".
    Get-Command npm -All | ForEach-Object Path