kovidgoyal/kitty · error

Could not find any writable data directories. Make sure XDG_

Error message

Could not find any writable data directories. Make sure XDG_DATA_DIRS is set and contains at least one directory for which you have write permission

What it means

enable_portal first checks WritableDataDirs(); if none of the XDG data directories is writable it aborts before writing anything. XDG_DATA_HOME and XDG_DATA_DIRS must yield at least one directory writable by the current user.

Source

Thrown at kittens/desktop_ui/portal.go:393

				lines = append(lines, line)
			}
		}
	}

	if !patched {
		// the file was empty or did not contain a section
		lines = append(lines, "[preferred]")
		for _, iface := range AllPortalInterfaces() {
			lines = append(lines, iface+"=kitty;*")
		}
	}

	return utils.UnsafeStringToBytes(strings.Join(lines, "\n"))
}

func enable_portal() (err error) {
	if len(WritableDataDirs()) == 0 {
		return fmt.Errorf("Could not find any writable data directories. Make sure XDG_DATA_DIRS is set and contains at least one directory for which you have write permission")
	}
	portals_dir := ""
	for _, x := range WritableDataDirs() {
		// Find-or-create the first available xdg-desktop-portals/portals directory
		q := filepath.Join(x, "xdg-desktop-portal", "portals")
		if (unix.Access(q, unix.W_OK) == nil && IsDir(q)) || (os.MkdirAll(q, 0o755) == nil) {
			portals_dir = q
			break
		}
	}
	if portals_dir == "" {
		return fmt.Errorf("Could not find any writable portals directories. Make sure XDG_DATA_HOME is set and point to a directory for which you have write permission.")
	}
	portals_defn := filepath.Join(portals_dir, "kitty.portal")
	if err = os.WriteFile(portals_defn, utils.UnsafeStringToBytes(fmt.Sprintf(
		`[portal]
DBusName=%s
Interfaces=%s;

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Set XDG_DATA_HOME to a writable path, e.g. export XDG_DATA_HOME=$HOME/.local/share
  2. Ensure the directory exists and you have write permission (mkdir -p && touch test)
  3. In containers, mount a writable volume at the data dir

Example fix

# before
unset XDG_DATA_HOME; kitten desktop-ui enable
# after
export XDG_DATA_HOME="$HOME/.local/share"; kitten desktop-ui enable
Defensive patterns

Strategy: validation

Validate before calling

home, _ := os.UserHomeDir()
dir := os.Getenv("XDG_DATA_HOME")
if dir == "" { dir = filepath.Join(home, ".local", "share") }
if err := os.MkdirAll(dir, 0o755); err != nil || unix.Access(dir, unix.W_OK) != nil {
    return errors.New("no writable XDG data dir")
}

Prevention

When it happens

Trigger: Running `kitten desktop-ui enable` with XDG_DATA_HOME/XDG_DATA_DIRS unset in a read-only or root-owned hierarchy, or as a user without write permission on those paths.

Common situations: Containers with read-only /usr/share; HOME unset so XDG_DATA_HOME resolves to /.local/share in an unwritable location; running as an unprivileged user against root-owned data dirs.

Related errors


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