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
- Set XDG_DATA_HOME to a writable path, e.g. export XDG_DATA_HOME=$HOME/.local/share
- Ensure the directory exists and you have write permission (mkdir -p && touch test)
- 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
- Set XDG_DATA_HOME explicitly in scripts
- Verify writability with a touch test before enabling the portal
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
- Could not find any writable portals directories. Make sure X
- failed to read the directory %s with error: %w
- Failed to create config directory to store favorites in: %w
- This kitten should be run as: kitten quick-access-terminal
- Incorrect owner on pwfile: uid={shm.stats.st_uid} gid={shm.s
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/b17544f35169d57e.
Report an issue: GitHub.