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
- 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`
- Or manually delete/rename the physical folder currently occupying the NVM_SYMLINK path (after confirming nothing of value is inside)
- Or edit settings.txt (symlink:PATH) / reinstall nvm-windows and choose a different NVM_SYMLINK location that is empty
- 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
- Never install standalone Node.js MSI and nvm-windows against the same target path
- Uninstall system-wide Node before installing nvm-windows
- Treat settings.txt symlink:PATH as reserved: keep it empty of real files
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
- failed to elevate permissions to create symlink
- scheduling error: invalid interval %q
- Invalid character(s) found in patch number %q
- scheduling error: %v %s
- unscheduling error: %v %s
AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15).
Data as JSON: /api/errors/c8ab8c6e30f30c17.
Report an issue: GitHub.