kovidgoyal/kitty · error
Could not find any writable portals directories. Make sure X
Error message
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.
What it means
enable_portal iterates writable data dirs trying to find-or-create <dir>/xdg-desktop-portal/portals. If none can be accessed or created (despite earlier writability checks), it fails before writing kitty.portal.
Source
Thrown at kittens/desktop_ui/portal.go:405
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;
`, PORTAL_BUS_NAME, strings.Join(AllPortalInterfaces(), ";"))), 0o644); err != nil {
return err
}
fmt.Println("Wrote kitty portal definition to:", portals_defn)
dbus_service_dir := ""
for _, x := range WritableDataDirs() {
q := filepath.Join(x, "dbus-1", "services")
if err := os.MkdirAll(q, 0o755); err == nil {
dbus_service_dir = q
break
}
}View on GitHub (pinned to 6d5d0c4406)
Solutions
- Check df -h and mount options for the data dir filesystem
- mkdir -p $XDG_DATA_HOME/xdg-desktop-portal/portals manually and fix any permission errors reported
- Remove any regular file blocking the path and retry enable
- Point XDG_DATA_HOME at a known-writable location
Defensive patterns
Strategy: validation
Validate before calling
q := filepath.Join(dataDir, "xdg-desktop-portal", "portals")
if err := os.MkdirAll(q, 0o755); err != nil || unix.Access(q, unix.W_OK) != nil {
return fmt.Errorf("cannot use portals dir %s", q)
} Prevention
- Pre-create the portals directory manually during provisioning
- Monitor disk space and read-only mounts
When it happens
Trigger: WritableDataDirs returned entries, but every xdg-desktop-portal/portals subdirectory fails unix.Access(W_OK) and os.MkdirAll (e.g. disk full, read-only mount, permission changed mid-run, path component is a file).
Common situations: Disk full or filesystem mounted read-only after boot; a regular file blocking a directory path component; sandboxed environments blocking mkdir.
Related errors
- Could not find any writable data directories. Make sure XDG_
- 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/058f0c6af9c770f6.
Report an issue: GitHub.