coreybutler/nvm-windows · warning
failed to set hidden attribute: %w
Error message
failed to set hidden attribute: %w
What it means
This error is returned when nvm-windows' upgrade routine fails to mark a file as hidden via the Win32 API SetFileAttributesW. The syscall's return value is 0, indicating the attribute was not applied, and the wrapped syscall error (often 'The operation completed successfully' from GetProcAddress-style calls) carries the real reason. Typical causes are missing permissions on the target file, the file being locked by another process, or the path pointer being invalid.
Source
Thrown at src/upgrade/upgrade.go:1075
func setHidden(path string) error {
// Convert the path to a UTF-16 encoded string
lpFileName, err := syscall.UTF16PtrFromString(path)
if err != nil {
return fmt.Errorf("failed to encode path: %w", err)
}
// Call the Windows API function
ret, _, err := syscall.NewLazyDLL("kernel32.dll").
NewProc("SetFileAttributesW").
Call(
uintptr(unsafe.Pointer(lpFileName)),
uintptr(FILE_ATTRIBUTE_HIDDEN),
)
// Check the result
if ret == 0 {
return fmt.Errorf("failed to set hidden attribute: %w", err)
}
return nil
}
View on GitHub (pinned to 5b18223ca1)
Solutions
- Close all terminals/processes using nvm.exe so the file is not locked, then retry the upgrade.
- Run the upgrade from an elevated (Administrator) prompt so SetFileAttributesW has permission.
- Verify the file path passed as lpFileName exists and is correctly UTF-16 encoded before the Call.
- Check the wrapped 'err' value in the message: a real errno (e.g. ERROR_ACCESS_DENIED) points to permissions; 'operation completed successfully' means ret==0 spuriously — re-check the path argument.
Example fix
// before
ret, _, err := syscall.NewLazyDLL("kernel32.dll").NewProc("SetFileAttributesW").Call(uintptr(unsafe.Pointer(lpFileName)), uintptr(FILE_ATTRIBUTE_HIDDEN))
if ret == 0 {
return fmt.Errorf("failed to set hidden attribute: %w", err)
}
// after: surface the Win32 error code when ret == 0 and err is the 'success' placeholder
if ret == 0 {
if err == syscall.Errno(0) {
return fmt.Errorf("failed to set hidden attribute on %s: SetFileAttributesW returned 0 (file locked or inaccessible)", fileName)
}
return fmt.Errorf("failed to set hidden attribute on %s: %w", fileName, err)
} Defensive patterns
Strategy: validation
Validate before calling
// Before upgrading / hiding files, confirm the target is not locked and exists
if _, err := os.Stat(fileName); err != nil {
return fmt.Errorf("cannot hide %s: %w", fileName, err)
}
// Ensure no running process holds the binary (best-effort on Windows)
cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("IMAGENAME eq %s", filepath.Base(fileName)))
out, _ := cmd.Output()
if !strings.Contains(string(out), "No tasks") {
return errors.New("file in use — close processes before upgrading")
} Try / catch
err := hideFile(path)
if err != nil {
// Non-fatal: hidden attribute is cosmetic for upgrade cleanup
log.Printf("warning: could not hide %s: %v", path, err)
} Prevention
- Close all node/npm/nvm processes before running an upgrade.
- Run the nvm upgrade from an elevated prompt.
- Keep the nvm installation in a user-writable directory so attribute writes succeed.
When it happens
Trigger: Calling the upgrade path in src/upgrade/upgrade.go that hides the old nvm.exe (or symlink target) after an upgrade, when SetFileAttributesW returns 0: target file is in use (running nvm.exe), path does not exist, or the process lacks WriteAttributes permission on the file.
Common situations: Upgrading nvm-windows while an nvm shell/command is still open; antivirus holding the binary; running from a directory where the user lacks NTFS attribute-write rights; UAC-elevated directory but non-elevated nvm.
Related errors
- error: failed to create backup directory: %v
- error: failed to copy update.exe: %v
- failed to open source file: %v
- failed to create destination file: %v
- failed to create destination directory %s: %v
AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15).
Data as JSON: /api/errors/cd22ad9977ce9cf9.
Report an issue: GitHub.