charmbracelet/glow · error
could not write configuration file: %w
Error message
could not write configuration file: %w
What it means
ensureConfigFile, when --config was not passed, takes configFile from viper.GetViper().ConfigFileUsed() and immediately does os.MkdirAll(filepath.Dir(configFile), 0o755) to make sure the parent directory exists. This error wraps that MkdirAll failure. It fires before extension checks or file creation, so it is about the directory, not the file.
Source
Thrown at config_cmd.go:60
return fmt.Errorf("unable to set config file: %w", err)
}
c.Stdin = os.Stdin
c.Stdout = os.Stdout
c.Stderr = os.Stderr
if err := c.Run(); err != nil {
return fmt.Errorf("unable to run command: %w", err)
}
fmt.Println("Wrote config file to:", configFile)
return nil
},
}
func ensureConfigFile() error {
if configFile == "" {
configFile = viper.GetViper().ConfigFileUsed()
if err := os.MkdirAll(filepath.Dir(configFile), 0o755); err != nil { //nolint:gosec
return fmt.Errorf("could not write configuration file: %w", err)
}
}
if ext := path.Ext(configFile); ext != ".yaml" && ext != ".yml" {
return fmt.Errorf("'%s' is not a supported configuration type: use '%s' or '%s'", ext, ".yaml", ".yml")
}
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)
}View on GitHub (pinned to e3970c813d)
Solutions
- Check ownership and permissions of the config dir: ls -ld ~/.config ~/.config/glow
- Take ownership: sudo chown -R $USER ~/.config
- Point elsewhere: glow config --config /tmp/glow.yml (on a writable path)
- Verify XDG_CONFIG_HOME/HOME are set to writable locations
Example fix
# before $ glow config # Error: could not write configuration file: mkdir /home/user/.config/glow: permission denied # after $ sudo chown -R "$USER" ~/.config && glow config
Defensive patterns
Strategy: validation
Validate before calling
func ensureConfigDirWritable(cfgPath string) error {
dir := filepath.Dir(cfgPath)
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("config dir %s unusable: %w", dir, err)
}
if !isWritable(dir) {
return fmt.Errorf("config dir %s is not writable by uid %d", dir, os.Getuid())
}
return nil
}
func isWritable(dir string) bool {
f, err := os.CreateTemp(dir, ".glow-probe-*")
if err != nil {
return false
}
_ = f.Close()
_ = os.Remove(f.Name())
return true
} Try / catch
if err := ensureConfigFile(); err != nil {
if strings.Contains(err.Error(), "could not write configuration file") {
// directory-level failure: report ownership hint instead of retrying blindly
fmt.Fprintf(os.Stderr, "fix perms on %s (chown -R $USER) or pass --config elsewhere\n", filepath.Dir(configFile))
os.Exit(1)
}
return err
} Prevention
- Never create glow's config directory with sudo if glow runs as your user
- Set XDG_CONFIG_HOME only to paths your user owns and can write
- Probe writability with os.CreateTemp in the config dir before first run in automation
When it happens
Trigger: The resolved config directory cannot be created or written: permission denied on an existing parent (e.g. ~/.config owned by root); the path component exists as a regular file; read-only filesystem or full disk; XDG_CONFIG_HOME pointing somewhere unwritable; ConfigFileUsed() returning an empty/unexpected value so Dir() resolves oddly.
Common situations: Running glow as a different user than the home owner after files were created with sudo; containers with a read-only /root; HOME unset so the config path collapses; disk quota exhausted.
Related errors
- unable create directory: %w
- unable to create config file: %w
- unable to stat config file: %w
- unable to write config file: %w
- specified style does not exist: %s
AI-assisted analysis of charmbracelet/glow@e3970c813d (2026-08-15).
Data as JSON: /api/errors/3898e4f445564579.
Report an issue: GitHub.