coreybutler/nvm-windows · error

failed to copy directory: %w

Error message

failed to copy directory: %w

What it means

After a successful os.Stat confirms the source is a directory, Rename() delegates to copyDir() to recursively copy it across volumes. This error means the recursive copy of at least one entry (or a subdirectory MkdirAll/ReadDir) failed; the wrapped chain (e.g. 'failed to read source directory: ...' or 'failed to copy file: ...') identifies the exact failing entry.

Source

Thrown at src/utility/rename.go:28

func Rename(old, new string) error {
	old_drive := filepath.VolumeName(old)
	new_drive := filepath.VolumeName(new)

	if old_drive == new_drive {
		return os.Rename(old, new)
	}

	// Get file or directory info
	info, err := os.Stat(old)
	if err != nil {
		return fmt.Errorf("failed to stat source: %w", err)
	}

	// 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
}

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Stop all node/npm processes so files in the version directory are not locked, then retry.
  2. Unwrap the error chain to find the failing entry — fix that specific file's lock/permission issue.
  3. Free space on the destination volume if the wrapped error is 'There is not enough space on the disk'.
  4. Retry from an elevated prompt if any wrapped error is 'Access is denied'.
Defensive patterns

Strategy: retry

Validate before calling

// Verify the tree is copyable: no running executables and destination has space
func canCopyDir(src, dst string) error {
    if _, err := os.ReadDir(src); err != nil { return err }
    if free := diskFree(dst); free <= neededSize(src) { return errors.New("insufficient space") }
    return nil
}

Try / catch

err := utility.Rename(old, new)
if err != nil && strings.Contains(err.Error(), "failed to copy directory") {
    // unwrap chain, unlock the named entry (kill node.exe), then retry once
    time.Sleep(time.Second)
    err = utility.Rename(old, new)
}

Prevention

When it happens

Trigger: utility.Rename(old, new) with different volume names where old is a directory, and copyDir fails: source dir becomes unreadable mid-copy (node.exe running from it), destination disk full, or a file inside is locked.

Common situations: Moving a node version directory between drives while a node process is running from it; destination drive out of space; antivirus scanning files during the copy; read-only attribute on files under the source tree.

Related errors


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