kovidgoyal/kitty · error

Failed to create config directory to store favorites in: %w

Error message

Failed to create config directory to store favorites in: %w

What it means

The unicode_input kitten stores your favorites (recently used characters) in a JSON file under the kitty config directory. Before writing, it creates the parent directory with os.MkdirAll; if creation fails (permission denied, read-only filesystem, a file exists where the directory should be), handle_favorites_key_event records this error and quits the kitten with exit code 1.

Source

Thrown at kittens/unicode_input/main.go:445

func (self *handler) handle_emoticons_key_event(event *loop.KeyEvent) {
}

func (self *handler) handle_favorites_key_event(event *loop.KeyEvent) {
	if event.MatchesPressOrRepeat("f12") {
		event.Handled = true
		exe, err := os.Executable()
		if err != nil {
			self.err = err
			self.lp.Quit(1)
			return
		}
		fp := favorites_path()
		if len(load_favorites(false)) == 0 || !favorites_loaded_from_user_config {
			raw := serialize_favorites(load_favorites(false))
			err = os.MkdirAll(filepath.Dir(fp), 0o755)
			if err != nil {
				self.err = fmt.Errorf("Failed to create config directory to store favorites in: %w", err)
				self.lp.Quit(1)
				return
			}
			err = utils.AtomicUpdateFile(fp, bytes.NewReader(utils.UnsafeStringToBytes(raw)), 0o600)
			if err != nil {
				self.err = fmt.Errorf("Failed to write to favorites file %s with error: %w", fp, err)
				self.lp.Quit(1)
				return
			}
		}
		err = self.lp.SuspendAndRun(func() error {
			cmd := exec.Command(exe, "edit-in-kitty", "--type=overlay", fp)
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err = cmd.Run()
			if err == nil {
				load_favorites(true)

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Check permissions on the config dir: mkdir -p ~/.config/kitty && chown -R $USER ~/.config
  2. Verify XDG_CONFIG_HOME (if set) points to a writable directory
  3. Remove any regular file blocking the directory path (e.g. a file named ~/.config/kitty)
  4. If sandboxed, grant write access to the config directory or unset favorites-related flows

Example fix

# before
$ ls -la ~/.config/kitty
-rw-r--r-- 1 root root /home/user/.config/kitty

# after
$ rm ~/.config/kitty
$ mkdir -p ~/.config/kitty && chown $USER ~/.config/kitty
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(favorites_path())
if info, err := os.Stat(dir); err == nil && !info.IsDir() {
    return fmt.Errorf("%s exists but is not a directory", dir)
}
if err := os.MkdirAll(dir, 0o755); err != nil {
    return fmt.Errorf("cannot create %s: %w", dir, err)
}

Try / catch

if err := os.MkdirAll(filepath.Dir(fp), 0o755); err != nil {
    log.Printf("skipping favorites save, config dir unwritable: %v", err)
    // continue without persisting favorites
}

Prevention

When it happens

Trigger: Pressing the favorites key (default f) in the unicode input kitten when ~/.config/kitty (or XDG_CONFIG_HOME equivalent) cannot be created — unwritable HOME, sandboxed environment, or a regular file occupying the config directory path.

Common situations: Running kitty/kitten in a container or sandbox with a read-only $HOME; wrong ownership of ~/.config after running with sudo; XDG_CONFIG_HOME pointing to an invalid path.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/50fd33db3ef25497. Report an issue: GitHub.