JanDeDobbeleer/oh-my-posh · error
unable to write font file: %s
Error message
unable to write font file: %s
What it means
The Windows installer writes the font bytes to `fontsDir\font.FileName` with `os.WriteFile(..., 0644)` and wraps any write failure with this message. At this point the directory exists and any old file was removed, so failures are almost always permission, disk-space, or AV-interference issues.
Source
Thrown at src/cli/font/install_windows.go:53
}
}
log.Debug("fonts directory exists, proceeding with installation")
fullPath := filepath.Join(fontsDir, font.FileName)
// validate if the font is already installed, remove it in case it is
if _, err := os.Stat(fullPath); err == nil {
log.Debugf("font %s already exists, removing it", fullPath)
if err = os.Remove(fullPath); err != nil {
return fmt.Errorf("unable to remove existing font file: %s", err.Error())
}
}
log.Debugf("writing font file to %s", fullPath)
err := os.WriteFile(fullPath, font.Data, 0644)
if err != nil {
return fmt.Errorf("unable to write font file: %s", err.Error())
}
log.Debug("font file written successfully, proceeding with registry entry")
// Add registry entry
reg := registry.CURRENT_USER
regValue := fullPath
log.Debug("opening HKEY_CURRENT_USER for writing (SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts)")
k, _, err := registry.CreateKey(reg, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts`, registry.WRITE)
if err != nil {
log.Error(err)
// If this fails, remove the font file as well.
if nexterr := os.Remove(fullPath); nexterr != nil {
log.Error(nexterr)
return errors.New("unable to delete font file after registry key open error")
}View on GitHub (pinned to 0976794618)
Solutions
- Run the terminal as Administrator for a machine-wide install, or use the default per-user install path (no elevation)
- Free disk space on the drive holding the fonts directory
- Temporarily exclude the fonts directory from real-time AV scanning and retry
- Retry — a transient file lock may have cleared
- Manually verify you can create a file in the fonts dir (`New-Item test.txt`) to confirm write access
Example fix
// before: non-elevated PS> oh-my-posh font install FiraCode # unable to write font file // after PS (admin)> oh-my-posh font install FiraCode
Defensive patterns
Strategy: validation
Validate before calling
# confirm write access and disk space first
$dir = "$env:LOCALAPPDATA\Microsoft\Windows\Fonts"
try { [IO.File]::WriteAllText("$dir\.wtest", "x"); Remove-Item "$dir\.wtest" }
catch { Write-Error "No write access to $dir"; exit 1 }
if ((Get-PSDrive ($dir[0]) ).Free -lt 50MB) { Write-Error 'Low disk space'; exit 1 } Prevention
- Verify write access to the fonts directory before batch installs
- Keep free disk space on the system drive
- Exclude the fonts directory from real-time AV scanning during installs
When it happens
Trigger: `os.WriteFile(fullPath, font.Data, 0644)` returns an error during `install` on Windows: access denied writing to C:\Windows\Fonts non-elevated, ERROR_DISK_FULL, or the just-removed file handle is still open by another process preventing recreation.
Common situations: Non-elevated shell attempting machine-wide install; full system drive; antivirus quarantine/race on newly created font files; another process re-created/locked the target path between Stat and WriteFile.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- unable to delete font file after registry key open error
- unable to create fonts directory: %s
- unable to open HKEY_CURRENT_USER
- unable to delete font file after registry key set error
- we do not have permissions to update
AI-assisted analysis of JanDeDobbeleer/oh-my-posh@0976794618 (2026-08-31).
Data as JSON: /api/errors/ea0f63f44b4c98b2.
Report an issue: GitHub.