coreybutler/nvm-windows · warning

failed to remove source

Error message

failed to remove source: %w

What it means

In Rename()'s cross-volume fallback, once the source has been successfully copied to the destination, os.RemoveAll(old) deletes the original. This error means that cleanup deletion failed. Data is usually NOT lost — the copy exists at the destination — but the stale source remains and the operation is reported as failed.

Solutions

  1. Since the copy already succeeded, simply delete the leftover source directory manually once no processes use it: rmdir /s /q <old>.
  2. Terminate node.exe/npm processes and re-run the original nvm command.
  3. Clear read-only attributes: attrib -r <old>\*.* /s /d, then delete.
  4. Run elevated if removal is denied by ACLs.
Defensive patterns

Strategy: fallback

Try / catch

if err := utility.Rename(old, new); err != nil {
    if strings.Contains(err.Error(), "failed to remove source") {
        // Copy already succeeded — treat as success and clean up later
        go os.RemoveAll(old)
        err = nil
    }
}

Prevention

When it happens

Trigger: utility.Rename(old, new) across volumes where the copy succeeded but the source tree cannot be removed: a file inside is open (running node.exe/npm.cmd), a read-only attribute blocks deletion, or another process (antivirus, indexer) holds a handle.

Common situations: Moving a node version while a terminal still has its npm.cmd or node.exe running; Windows Search or Defender transiently holding handles; source files marked read-only after being restored from backup.

Related errors


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

Appendix: source

Thrown at src/utility/rename.go:41

	// If old is a directory, copy recursively
	if info.IsDir() {
		err = copyDir(old, new)
		if err != nil {
			return fmt.Errorf("failed to copy directory: %w", err)
		}
	} else {
		// Otherwise, copy a single file
		err = copyFile(old, new)
		if err != nil {
			return fmt.Errorf("failed to copy file: %w", err)
		}
	}

	// Remove the original source
	err = os.RemoveAll(old)
	if err != nil {
		return fmt.Errorf("failed to remove source: %w", err)
	}

	return nil
}

// copyFile copies a single file from source (old) to destination (new).
func copyFile(old, new string) error {
	srcFile, err := os.Open(old)
	if err != nil {
		return fmt.Errorf("failed to open source file: %w", err)
	}
	defer srcFile.Close()

	// Ensure destination directory exists
	destDir := filepath.Dir(new)
	err = os.MkdirAll(destDir, os.ModePerm)
	if err != nil {
		return fmt.Errorf("failed to create destination directory: %w", err)

View on GitHub (pinned to 5b18223ca1)