charmbracelet/glow · error

unable to stat config file: %w

Error message

unable to stat config file: %w

What it means

ensureConfigFile calls os.Stat(configFile) to decide whether the default config must be written. errors.Is(err, fs.ErrNotExist) takes the create branch, but any other stat error — the else-if at the end — is surfaced with this wrapper. So the file's existence is undetermined, not merely absent.

Source

Thrown at config_cmd.go:85

	if _, err := os.Stat(configFile); errors.Is(err, fs.ErrNotExist) {
		// File doesn't exist yet, create all necessary directories and
		// write the default config file
		if err := os.MkdirAll(filepath.Dir(configFile), 0o700); err != nil {
			return fmt.Errorf("unable create directory: %w", err)
		}

		f, err := os.Create(configFile)
		if err != nil {
			return fmt.Errorf("unable to create config file: %w", err)
		}
		defer func() { _ = f.Close() }()

		if _, err := f.WriteString(defaultConfig); err != nil {
			return fmt.Errorf("unable to write config file: %w", err)
		}
	} else if err != nil { // some other error occurred
		return fmt.Errorf("unable to stat config file: %w", err)
	}
	return nil
}

View on GitHub (pinned to e3970c813d)

Solutions

  1. Reproduce manually: stat <configFile> and namei -l <configFile> to find the failing component
  2. Fix traversal permissions: chmod o+x on the blocking directory or chown it
  3. Remove broken symlinks in the path: rm ~/.config/glow (symlink) then retry
  4. Fall back to a clean --config path you control

Example fix

# before
$ glow config
# Error: unable to stat config file: stat /home/u/.config/glow/glow.yml: permission denied

# after
$ chmod 755 /home/u/.config && glow config
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-walk the path so a non-NotExist stat failure is caught with context
func probeConfigPath(p string) error {
	_, err := os.Stat(p)
	switch {
	case err == nil, errors.Is(err, fs.ErrNotExist):
		return nil
	case errors.Is(err, fs.ErrPermission):
		return fmt.Errorf("cannot traverse to %s: fix mode/ownership on a parent dir", p)
	default:
		return fmt.Errorf("cannot stat %s: %w", p, err)
	}
}

Try / catch

if _, err := os.Stat(configFile); err != nil && !errors.Is(err, fs.ErrNotExist) {
	if errors.Is(err, fs.ErrPermission) {
		// traversal problem in a parent directory, not the file itself
		return fmt.Errorf("unable to stat config file (check parent dir modes with namei -l): %w", err)
	}
	return fmt.Errorf("unable to stat config file: %w", err)
}

Prevention

When it happens

Trigger: Search/execute permission denied on a parent directory component, so stat cannot traverse to the file (EACCES); a symlink in the path with a broken/looping target causing a non-NotExist error; path longer than PATH_MAX; SELinux denying stat on the context.

Common situations: chmod 700 directories owned by another user inside the config path; broken symlink left by a dotfile manager at ~/.config/glow; odd mount namespaces (containers) where a bind-mounted parent disappears.

Related errors


AI-assisted analysis of charmbracelet/glow@e3970c813d (2026-08-15). Data as JSON: /api/errors/825302d946bebe27. Report an issue: GitHub.