coreybutler/nvm-windows · warning

failed to set file permissions: %v

Error message

failed to set file permissions: %v

What it means

copyFile's final step applies the source file's permission bits to the destination with os.Chmod, and this error means that failed. On Windows, Chmod maps to SetFileInformationByHandle and can be denied when the destination handle is still open (the deferred Close has not run yet) or when ACLs on the destination forbid the change. The data copy itself already succeeded, so the file exists but may carry default permissions.

Source

Thrown at src/upgrade/upgrade.go:949

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

	return nil
}

// copyDirContents copies all the contents (files and subdirectories) of a source directory to a destination directory.
func copyDirContents(srcDir, dstDir string) error {
	// Ensure destination directory exists
	err := os.MkdirAll(dstDir, 0755)
	if err != nil {
		return fmt.Errorf("failed to create destination directory %s: %v", dstDir, err)
	}

	// Walk through the source directory recursively
	err = filepath.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
		if err != nil {
			return fmt.Errorf("error accessing %s: %v", srcPath, err)
		}

View on GitHub (pinned to 5b18223ca1)

Solutions

  1. Run the upgrade elevated so permission changes under NVM_HOME succeed.
  2. Check inherited ACLs/attributes on the destination directory (attrib -r, icacls) and clear read-only inheritance.
  3. Treat as non-fatal if present: the copied bytes are valid; re-running as admin fixes modes.

Example fix

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

// after: close handles before chmod and tolerate failure on Windows
destinationFile.Close()
sourceFile.Close()
if err := os.Chmod(dst, sourceInfo.Mode()); err != nil {
    // permissions are advisory on Windows; log but do not fail the copy
    utility.DebugLogf("chmod %s: %v", dst, err)
}
Defensive patterns

Strategy: fallback

Try / catch

Permission mirroring is optional: catch the Chmod error, log it, and return nil so the copied file is used as-is. Only fail when a later exec of the copied binary proves permissions actually matter.

Prevention

When it happens

Trigger: Destination under a directory with restrictive ACLs (Program Files without elevation); the still-open destinationFile handle conflicting with the mode change; read-only attribute on the destination inherited from the directory.

Common situations: Non-admin installs into protected paths; group-policy ACL inheritance marking files read-only; enterprise lockdown tools reverting permission changes.

Related errors


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