kovidgoyal/kitty · error

Failed to write to favorites file %s with error: %w

Error message

Failed to write to favorites file %s with error: %w

What it means

After ensuring the config directory exists, the unicode_input kitten writes the serialized favorites JSON atomically via utils.AtomicUpdateFile with mode 0600. If that write fails (disk full, permission denied, favorites.json is a directory or owned by another user), the kitten stores this error and exits with code 1.

Source

Thrown at kittens/unicode_input/main.go:451

		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)
			} else {
				fmt.Fprintln(os.Stderr, err)
				fmt.Fprintln(os.Stderr, "Failed to run edit-in-kitty, favorites have not been changed. Press Enter to continue.")
				var ln string
				fmt.Scanln(&ln)
			}

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Fix ownership: sudo chown -R $USER ~/.config/kitty
  2. Check disk space and quota: df -h ~
  3. If favorites.json is a directory or corrupt, remove it: rm -rf ~/.config/kitty/unicode_input/favorites.json (it will be recreated)
  4. On read-only setups, pre-create a writable config dir and point XDG_CONFIG_HOME at it

Example fix

# before
$ ls -l ~/.config/kitty/unicode_input/favorites.json
-rw------- 1 root root ... favorites.json

# after
$ sudo chown $USER:$USER ~/.config/kitty/unicode_input/favorites.json
Defensive patterns

Strategy: try-catch

Validate before calling

fp := favorites_path()
if _, err := os.Stat(fp); err == nil {
    if info, _ := os.Stat(fp); info != nil && !info.Mode().IsRegular() {
        return fmt.Errorf("favorites path %s is not a regular file", fp)
    }
    if err := os.Chmod(fp, 0o600); err != nil {
        return fmt.Errorf("favorites file not writable: %w", err)
    }
}

Try / catch

if err := utils.AtomicUpdateFile(fp, bytes.NewReader(raw), 0o600); err != nil {
    log.Printf("could not save favorites to %s: %v (continuing)", fp, err)
}

Prevention

When it happens

Trigger: Pressing the favorites key in the unicode input kitten when the favorites file path is unwritable — favorites.json owned by root, read-only mount, or I/O errors during the atomic rename/temp file creation.

Common situations: Previously ran kitty with sudo so ~/.config/kitty/unicode_input/favorites.json is root-owned; disk quota exhausted; the favorites file was replaced by a directory; synced/dropbox-held config dirs with transient lock issues.

Related errors


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