coreybutler/nvm-windows · error

failed to create destination directory: %w

Error message

failed to create destination directory: %w

What it means

In copyFile(), after opening the source, os.MkdirAll(filepath.Dir(new), os.ModePerm) prepares the destination directory tree. This error means that directory creation failed — typically because a component of the parent path exists as a FILE (ENOTDIR), a permission denial, or an invalid path (illegal characters, trailing spaces).

Source

Thrown at src/utility/rename.go:59

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

	destFile, err := os.Create(new)
	if err != nil {
		return fmt.Errorf("failed to create destination file: %w", err)
	}
	defer destFile.Close()

	_, err = io.Copy(destFile, srcFile)
	if err != nil {
		return fmt.Errorf("failed to copy data: %w", err)
	}

	// Copy file permissions
	info, err := srcFile.Stat()
	if err != nil {
		return fmt.Errorf("failed to get source file info: %w", err)
	}

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Check the wrapped error: 'The system cannot find the path specified' usually means a parent component is a file — remove the conflicting file.
  2. Verify NVM_HOME/NVM_SYMLINK point to writable locations and the drive is mounted.
  3. Run elevated when writing under protected directories.
  4. Retry the nvm command after cleaning the partially-created destination directory.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the destination parent is a directory, not blocked by a file
func ensureDir(p string) error {
    if info, err := os.Stat(p); err == nil && !info.IsDir() {
        return fmt.Errorf("%s exists and is not a directory", p)
    }
    return os.MkdirAll(p, 0o755)
}

Try / catch

if err := copyAcrossDrives(old, new); err != nil && strings.Contains(err.Error(), "destination directory") {
    // remove the conflicting file at the reported path, then retry
    os.Remove(filepath.Dir(new))
    err = copyAcrossDrives(old, new)
}

Prevention

When it happens

Trigger: copyFile where the destination's parent path collides with an existing regular file, the destination drive is unavailable/read-only, or the path contains characters Windows rejects (e.g. reserved names like CON, NUL).

Common situations: Destination node version directory partially created by an earlier failed install so a directory name is occupied by a file; running non-elevated against C:\Program Files; mistyped NVM_HOME pointing at a nonexistent or read-only drive.

Related errors


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