{"record":{"id":"058f0c6af9c770f6","repo":"kovidgoyal/kitty","slug":"could-not-find-any-writable-portals-directories-m","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kittens/desktop_ui/portal.go","lineNumber":405,"sourceCode":"\n\treturn utils.UnsafeStringToBytes(strings.Join(lines, \"\\n\"))\n}\n\nfunc enable_portal() (err error) {\n\tif len(WritableDataDirs()) == 0 {\n\t\treturn 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\")\n\t}\n\tportals_dir := \"\"\n\tfor _, x := range WritableDataDirs() {\n\t\t// Find-or-create the first available xdg-desktop-portals/portals directory\n\t\tq := filepath.Join(x, \"xdg-desktop-portal\", \"portals\")\n\t\tif (unix.Access(q, unix.W_OK) == nil && IsDir(q)) || (os.MkdirAll(q, 0o755) == nil) {\n\t\t\tportals_dir = q\n\t\t\tbreak\n\t\t}\n\t}\n\tif portals_dir == \"\" {\n\t\treturn 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.\")\n\t}\n\tportals_defn := filepath.Join(portals_dir, \"kitty.portal\")\n\tif err = os.WriteFile(portals_defn, utils.UnsafeStringToBytes(fmt.Sprintf(\n\t\t`[portal]\nDBusName=%s\nInterfaces=%s;\n`, PORTAL_BUS_NAME, strings.Join(AllPortalInterfaces(), \";\"))), 0o644); err != nil {\n\t\treturn err\n\t}\n\tfmt.Println(\"Wrote kitty portal definition to:\", portals_defn)\n\tdbus_service_dir := \"\"\n\tfor _, x := range WritableDataDirs() {\n\t\tq := filepath.Join(x, \"dbus-1\", \"services\")\n\t\tif err := os.MkdirAll(q, 0o755); err == nil {\n\t\t\tdbus_service_dir = q\n\t\t\tbreak\n\t\t}\n\t}","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/desktop_ui/portal.go#L387-L423","documentation":"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.","triggerScenarios":"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).","commonSituations":"Disk full or filesystem mounted read-only after boot; a regular file blocking a directory path component; sandboxed environments blocking mkdir.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"q := filepath.Join(dataDir, \"xdg-desktop-portal\", \"portals\")\nif err := os.MkdirAll(q, 0o755); err != nil || unix.Access(q, unix.W_OK) != nil {\n    return fmt.Errorf(\"cannot use portals dir %s\", q)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-create the portals directory manually during provisioning","Monitor disk space and read-only mounts"],"tags":["xdg","desktop-ui","kitty","filesystem","permissions"],"backgroundTag":"xdg-data-dir-not-writable","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}