charmbracelet/glow · error
unable to stat file: %w
Error message
unable to stat file: %w
What it means
The same validateStyle stat call, but for errors other than fs.ErrNotExist - the raw OS error is wrapped with %w. This means the style path could be located but stat-ing it failed: a parent directory lacks search permission (EACCES), a stale network mount (EIO), or the path exceeds limits (ENAMETOOLONG).
Source
Thrown at main.go:160
if err != nil {
return nil, fmt.Errorf("unable to open file: %w", err)
}
u, err := filepath.Abs(arg)
if err != nil {
return nil, fmt.Errorf("unable to get absolute path: %w", err)
}
return &source{r, u}, nil
}
// validateStyle checks if the style is a default style, if not, checks that
// the custom style exists.
func validateStyle(style string) error {
if style != "auto" && styles.DefaultStyles[style] == nil {
style = utils.ExpandPath(style)
if _, err := os.Stat(style); errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("specified style does not exist: %s", style)
} else if err != nil {
return fmt.Errorf("unable to stat file: %w", err)
}
}
return nil
}
func validateOptions(cmd *cobra.Command) error {
// grab config values from Viper
width = viper.GetUint("width")
mouse = viper.GetBool("mouse")
pager = viper.GetBool("pager")
tui = viper.GetBool("tui")
showAllFiles = viper.GetBool("all")
preserveNewLines = viper.GetBool("preserveNewLines")
showLineNumbers = viper.GetBool("showLineNumbers")
if pager && tui {
return errors.New("cannot use both pager and tui")
}View on GitHub (pinned to e3970c813d)
Solutions
- Check traversability of each component: namei -l /path/to/style.json
- Repair or remount stale network mounts
- Shorten the path or move the style file to local disk
Defensive patterns
Strategy: try-catch
Validate before calling
func traversable(path string) error {
for dir := path; dir != "/" && dir != "."; dir = filepath.Dir(dir) {
if _, err := os.Stat(dir); err != nil { return fmt.Errorf("%s: %w", dir, err) }
}
return nil
} Type guard
func isPermissionErr(err error) bool { return errors.Is(err, fs.ErrPermission) } Try / catch
if _, err := os.Stat(stylePath); err != nil {
switch {
case errors.Is(err, fs.ErrNotExist):
// style file missing: use a built-in style
case errors.Is(err, fs.ErrPermission):
// parent traversal denied: report the offending dir
default:
// I/O or path-length error: surface the wrapped error
}
} Prevention
- Distinguish fs.ErrNotExist from fs.ErrPermission and I/O errors when stat-ing style files
- Keep style files on local disk rather than network mounts
- Audit parent-directory permissions after moving configs
When it happens
Trigger: A parent directory in the style path is not traversable by the user; the style file sits on a stale NFS/fuse mount; the path is longer than PATH_MAX.
Common situations: Styles kept on network home directories that went stale, restricted multi-user machines, deeply nested config directories exceeding path limits.
Related errors
- could not write configuration file: %w
- unable create directory: %w
- unable to create config file: %w
- unable to stat config file: %w
- specified style does not exist: %s
AI-assisted analysis of charmbracelet/glow@e3970c813d (2026-08-15).
Data as JSON: /api/errors/191d7e666ddb1388.
Report an issue: GitHub.