charmbracelet/glow · error

unable create directory: %w

Error message

unable create directory: %w

What it means

In the branch where the config file does not exist yet (os.Stat returned fs.ErrNotExist), ensureConfigFile first creates the containing directory with os.MkdirAll(dir, 0o700) before writing the default config. This error wraps that MkdirAll failure. Note the 0o700 mode here versus the 0o755 pre-check earlier — both must succeed.

Source

Thrown at config_cmd.go:72

}

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)
		}
		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. Create the directory manually with correct ownership: mkdir -p ~/.config/glow && chown $USER ~/.config/glow
  2. Remove anything occupying the path that should be a directory: rm ~/.config/glow (if it is a file)
  3. Use an alternative writable location: glow config --config /path/with/access/glow.yml
  4. Free disk space or fix quota if writes fail filesystem-wide

Example fix

# before
$ glow config
# Error: unable create directory: mkdir /home/u/.config/glow: file exists

# after
$ rm /home/u/.config/glow && glow config   # was a file, now a dir is created
Defensive patterns

Strategy: validation

Validate before calling

func prepNewConfigDir(cfgPath string) error {
	dir := filepath.Dir(cfgPath)
	if fi, err := os.Stat(dir); err == nil && !fi.IsDir() {
		return fmt.Errorf("%s exists but is not a directory", dir)
	}
	if err := os.MkdirAll(dir, 0o700); err != nil {
		return fmt.Errorf("cannot create config dir: %w", err)
	}
	return nil
}

Try / catch

if err := ensureConfigFile(); err != nil {
	if strings.Contains(err.Error(), "unable create directory") {
		// pre-clear the path: it is a file/symlink squatting on the dir name
		if fi, statErr := os.Stat(filepath.Dir(configFile)); statErr == nil && !fi.IsDir() {
			_ = os.Remove(filepath.Dir(configFile))
			return ensureConfigFile()
		}
	}
	return err
}

Prevention

When it happens

Trigger: First-run creation where the config directory's parent is unwritable or owned by another user; a path component already existing as a non-directory file; read-only or full filesystem; SELinux/AppArmor denying mkdir in the config location.

Common situations: First launch in a container as non-root with root-owned /home/user; home directory on a full disk quota; ~/.config/glow existing as a file instead of a directory.

Related errors


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