coreybutler/nvm-windows · error

failed to create destination file: %v

Error message

failed to create destination file: %v

What it means

copyFile failed at os.Create(dst): the destination file could not be created. On Windows this is dominated by sharing violations — the destination exists and is open by a running process (often nvm.exe or node.exe itself), since Windows refuses to create/truncate a file with an active handle. It also fires when the parent directory of dst does not exist or is read-only.

Source

Thrown at src/upgrade/upgrade.go:931

	if err != nil {
		return "", err
	}

	return checksum, nil
}

func copyFile(src, dst string) error {
	// Open the source file
	sourceFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("failed to open source file: %v", err)
	}
	defer sourceFile.Close()

	// Create the destination file
	destinationFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("failed to create destination file: %v", err)
	}
	defer destinationFile.Close()

	// Copy contents from the source file to the destination file
	_, err = io.Copy(destinationFile, sourceFile)
	if err != nil {
		return fmt.Errorf("failed to copy file: %v", err)
	}

	// Optionally, copy file permissions (this can be skipped if not needed)
	sourceInfo, err := os.Stat(src)
	if err != nil {
		return fmt.Errorf("failed to get source file info: %v", err)
	}

	err = os.Chmod(dst, sourceInfo.Mode())
	if err != nil {
		return fmt.Errorf("failed to set file permissions: %v", err)

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Stop all nvm/node processes (check Task Manager) and retry the upgrade.
  2. Run the upgrade from an elevated prompt.
  3. Ensure the destination directory exists and is writable (attrib -r on NVM_HOME files if read-only bits were inherited).
  4. Reinstall nvm-windows cleanly if the destination tree is in a bad state.

Example fix

// before
destinationFile, err := os.Create(dst)

// after: create parent directories first, then the file
_ = os.MkdirAll(filepath.Dir(dst), 0755)
destinationFile, err := os.Create(dst)
Defensive patterns

Strategy: validation

Validate before calling

// Ensure parent dir exists and dest is not currently executing
os.MkdirAll(filepath.Dir(dst), 0755)
if _, err := os.Stat(dst); err == nil {
    if out, _ := exec.Command("tasklist", "/FI", "IMAGENAME eq "+filepath.Base(dst)).Output(); !strings.Contains(string(out), "No tasks") {
        return fmt.Errorf("destination %s is in use; close it first", dst)
    }
}

Try / catch

On Windows sharing violations, instruct closing the destination process rather than retrying in-process; retry only after the lock holder is gone.

Prevention

When it happens

Trigger: Copying nvm.exe/update.exe over binaries that are currently executing; dst parent directory missing (copyFile does not mkdir parents); NVM_HOME on a read-only or ACL-restricted location; .update hidden directory unwritable.

Common situations: Self-update attempted while another nvm command runs in a second terminal; non-admin install under Program Files; .update folder marked read-only by policy; leftover read-only attribute on files extracted from the zip.

Related errors


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