{"record":{"id":"770ca116112499dc","repo":"charmbracelet/glow","slug":"unable-create-directory-w","errorCode":null,"errorMessage":"unable create directory: %w","messagePattern":"unable create directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config_cmd.go","lineNumber":72,"sourceCode":"}\n\nfunc ensureConfigFile() error {\n\tif configFile == \"\" {\n\t\tconfigFile = viper.GetViper().ConfigFileUsed()\n\t\tif err := os.MkdirAll(filepath.Dir(configFile), 0o755); err != nil { //nolint:gosec\n\t\t\treturn fmt.Errorf(\"could not write configuration file: %w\", err)\n\t\t}\n\t}\n\n\tif ext := path.Ext(configFile); ext != \".yaml\" && ext != \".yml\" {\n\t\treturn fmt.Errorf(\"'%s' is not a supported configuration type: use '%s' or '%s'\", ext, \".yaml\", \".yml\")\n\t}\n\n\tif _, err := os.Stat(configFile); errors.Is(err, fs.ErrNotExist) {\n\t\t// File doesn't exist yet, create all necessary directories and\n\t\t// write the default config file\n\t\tif err := os.MkdirAll(filepath.Dir(configFile), 0o700); err != nil {\n\t\t\treturn fmt.Errorf(\"unable create directory: %w\", err)\n\t\t}\n\n\t\tf, err := os.Create(configFile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to create config file: %w\", err)\n\t\t}\n\t\tdefer func() { _ = f.Close() }()\n\n\t\tif _, err := f.WriteString(defaultConfig); err != nil {\n\t\t\treturn fmt.Errorf(\"unable to write config file: %w\", err)\n\t\t}\n\t} else if err != nil { // some other error occurred\n\t\treturn fmt.Errorf(\"unable to stat config file: %w\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":54,"sourceCodeEnd":89,"githubUrl":"https://github.com/charmbracelet/glow/blob/e3970c813d93da1ea84edfca90c289d9afb82242/config_cmd.go#L54-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Create the directory manually with correct ownership: mkdir -p ~/.config/glow && chown $USER ~/.config/glow","Remove anything occupying the path that should be a directory: rm ~/.config/glow (if it is a file)","Use an alternative writable location: glow config --config /path/with/access/glow.yml","Free disk space or fix quota if writes fail filesystem-wide"],"exampleFix":"# before\n$ glow config\n# Error: unable create directory: mkdir /home/u/.config/glow: file exists\n\n# after\n$ rm /home/u/.config/glow && glow config   # was a file, now a dir is created","handlingStrategy":"validation","validationCode":"func prepNewConfigDir(cfgPath string) error {\n\tdir := filepath.Dir(cfgPath)\n\tif fi, err := os.Stat(dir); err == nil && !fi.IsDir() {\n\t\treturn fmt.Errorf(\"%s exists but is not a directory\", dir)\n\t}\n\tif err := os.MkdirAll(dir, 0o700); err != nil {\n\t\treturn fmt.Errorf(\"cannot create config dir: %w\", err)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if err := ensureConfigFile(); err != nil {\n\tif strings.Contains(err.Error(), \"unable create directory\") {\n\t\t// pre-clear the path: it is a file/symlink squatting on the dir name\n\t\tif fi, statErr := os.Stat(filepath.Dir(configFile)); statErr == nil && !fi.IsDir() {\n\t\t\t_ = os.Remove(filepath.Dir(configFile))\n\t\t\treturn ensureConfigFile()\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Ensure ~/.config/glow is a directory owned by the running user before first launch","In Dockerfiles, pre-create it: RUN mkdir -p /root/.config/glow","Watch for dotfile managers placing a file (not a symlink) where the directory belongs"],"tags":["config","filesystem","permissions","first-run"],"backgroundTag":null,"analyzedSha":"e3970c813d93da1ea84edfca90c289d9afb82242","analyzedAt":"2026-08-15T22:50:54.304Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}