Kareadita/Kavita · error · KavitaException

bookmark-dir-permissions

bookmark-dir-permissions

Error message

bookmark-dir-permissions

What it means

Thrown by SettingsService when updating ServerSettingKey.BookmarkDirectory and directoryService.CheckWriteAccess(bookmarkDirectory) returns false. Kavita writes user bookmarks (saved pages) into this directory, so it must be writable by the process; the guard fails fast rather than silently dropping bookmarks later.

Source

Thrown at Kavita.Services/SettingsService.cs:421

                ((int)updateSettingsDto.PdfRenderResolution).ToString() != setting.Value)
            {
                setting.Value = ((int)updateSettingsDto.PdfRenderResolution).ToString();
                unitOfWork.SettingsRepository.Update(setting);
            }

            if (setting.Key == ServerSettingKey.HostName && updateSettingsDto.HostName + string.Empty != setting.Value)
            {
                setting.Value = (updateSettingsDto.HostName + string.Empty).Trim();
                setting.Value = UrlHelper.RemoveEndingSlash(setting.Value);
                unitOfWork.SettingsRepository.Update(setting);
            }

            if (setting.Key == ServerSettingKey.BookmarkDirectory && bookmarkDirectory != setting.Value)
            {
                // Validate new directory can be used
                if (!await directoryService.CheckWriteAccess(bookmarkDirectory))
                {
                    throw new KavitaException("bookmark-dir-permissions");
                }

                originalBookmarkDirectory = setting.Value;

                // Normalize the path deliminators. Just to look nice in DB, no functionality
                setting.Value = directoryService.FileSystem.Path.GetFullPath(bookmarkDirectory);
                unitOfWork.SettingsRepository.Update(setting);
                updateBookmarks = true;

            }

            if (setting.Key == ServerSettingKey.AllowStatCollection &&
                updateSettingsDto.AllowStatCollection + string.Empty != setting.Value)
            {
                setting.Value = updateSettingsDto.AllowStatCollection + string.Empty;
                unitOfWork.SettingsRepository.Update(setting);
            }

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Ensure the directory exists and the Kavita process user has write permission (chmod/chown on Linux).
  2. For Docker, mount the bookmark volume read-write (drop ':ro').
  3. Pick a directory inside the existing writable data directory.
  4. Run CheckWriteAccess manually with the Kavita user to confirm permissions before saving.

Example fix

// before
updateSettingsDto.BookmarkDirectory = "/mnt/readonly/bookmarks";
await settingsService.UpdateSettings(updateSettingsDto);

// after
sudo mkdir -p /var/lib/kavita/bookmarks && sudo chown kavita:kavita /var/lib/kavita/bookmarks
updateSettingsDto.BookmarkDirectory = "/var/lib/kavita/bookmarks";
await settingsService.UpdateSettings(updateSettingsDto);
Defensive patterns

Strategy: validation

Validate before calling

if (!await directoryService.CheckWriteAccess(bookmarkDirectory))
    return BadRequest("bookmark-dir-permissions");
updateSettingsDto.BookmarkDirectory = bookmarkDirectory;
await settingsService.UpdateSettings(updateSettingsDto);

Type guard

static async Task<bool> DirectoryIsWritable(string path, IDirectoryService ds) => await ds.CheckWriteAccess(path);

Prevention

When it happens

Trigger: Saving server settings with a BookmarkDirectory that the Kavita process cannot write to - missing directory, read-only mount, insufficient filesystem permissions, or an invalid path.

Common situations: Docker volume mounted read-only; SELinux/AppArmor denying writes; bookmark path on a network share without write perms; non-existent directory that CheckWriteAccess doesn't auto-create; or path with a typo.

Related errors


AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13). Data as JSON: /api/errors/08ffdd39aae01a10. Report an issue: GitHub.