coreybutler/nvm-windows · error

NVM_SYMLINK is set to a physical file/directory at %s Please

Error message

NVM_SYMLINK is set to a physical file/directory at %s
Please remove the location and try again, or select a different location for NVM_SYMLINK.

What it means

Safety check in validSymlink() before `nvm use` replaces the NVM_SYMLINK path: if the symlink location exists but is a real physical file/directory (not a symlink/junction), nvm refuses to touch it to avoid deleting user data. It fires when isSymlink(path) reports 'not a symlink' with no error, i.e. something real occupies the location.

Source

Thrown at src/nvm.go:1277

	wg.Wait()
	os.Exit(exitCode)
}

func abortOnBadSymlink(symlinkpath string) {
	if err := validSymlink(symlinkpath); err != nil {
		fmt.Printf("%v\n", err)
		os.Exit(1)
	}
}

func validSymlink(symlinkpath string) error {
	symlinkpath = filepath.Clean(symlinkpath)
	// Prevent deletion if the symlink has been set to a physical directpry/file.
	// This isn't supposed to ever happen, but users have manually changed the settings.txt,
	// removing the physical file/directory unintentionally.
	// This is an anti-footgun.
	if symlink, err := isSymlink(symlinkpath); !symlink && err == nil {
		return fmt.Errorf("NVM_SYMLINK is set to a physical file/directory at %s\nPlease remove the location and try again, or select a different location for NVM_SYMLINK.\n", env.symlink)
	}

	return nil
}

func useArchitecture(a string) {
	if strings.ContainsAny("32", os.Getenv("PROCESSOR_ARCHITECTURE")) {
		fmt.Println("This computer only supports 32-bit processing.")
		return
	}
	if strings.Contains("arm64", strings.ToLower(os.Getenv("PROCESSOR_ARCHITECTURE"))) {
		fmt.Println("This computer only supports arm64-bit processing.")
		return
	}
	if a == "32" || a == "64" {
		env.arch = a
		saveSettings()
		fmt.Println("Set to " + a + "-bit mode")

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Uninstall the standalone Node.js (Control Panel > Node.js) so its real directory at e.g. C:\Program Files\nodejs is removed, then re-run `nvm use`
  2. Or manually delete/rename the physical folder currently occupying the NVM_SYMLINK path (after confirming nothing of value is inside)
  3. Or edit settings.txt (symlink:PATH) / reinstall nvm-windows and choose a different NVM_SYMLINK location that is empty
  4. Verify afterwards with `cmd /c dir /AL <parent>` that the target is now absent before retrying

Example fix

# before
# settings.txt: symlink: C:\Program Files\nodejs  (real dir from old MSI install)
nvm use 20.11.0
# -> NVM_SYMLINK is set to a physical file/directory...

# after
# uninstall standalone Node.js, or move the folder, then:
nvm use 20.11.0
Defensive patterns

Strategy: validation

Validate before calling

func isJunction(path string) bool {
    fi, err := os.Lstat(path)
    if err != nil { return false }
    return fi.Mode()&os.ModeSymlink != 0
}
// before nvm use:
if _, err := os.Lstat(env.Symlink); err == nil && !isJunction(env.Symlink) {
    log.Fatal("refusing to run: NVM_SYMLINK occupied by real data; move it first")
}

Prevention

When it happens

Trigger: Any `nvm use` (or nvm install triggering a use) where env.symlink points at an ordinary directory or file — commonly C:\Program Files\nodejs left behind by a standalone Node.js MSI install, or a user-created folder at the configured NVM_SYMLINK location.

Common situations: Installing nvm-windows on a machine that already had Node.js installed system-wide (the MSI's real directory sits at the symlink target); manually editing settings.txt to point root:PATH at a real folder; a previous junction converted into a copy by backup/restore software.

Related errors


AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15). Data as JSON: /api/errors/c8ab8c6e30f30c17. Report an issue: GitHub.