Kareadita/Kavita · warning · KavitaException

errors.delete-theme-in-use

errors.delete-theme-in-use

Error message

errors.delete-theme-in-use

What it means

Thrown by SiteThemeService.DeleteTheme when SiteThemeRepository.IsThemeInUse(siteThemeId) is true, i.e. at least one user has this theme selected as their active preference. Kavita protects users from losing their theme by blocking deletion; it throws KavitaException('errors.delete-theme-in-use'). ThemeController.DeleteTheme does not catch it, so it bubbles to ExceptionMiddleware and returns HTTP 500 with the raw key string 'errors.delete-theme-in-use'.

Source

Thrown at Kavita.Services/SiteThemeService.cs:396

        await eventHub.SendMessageAsync(MessageFactory.NotificationProgress,
            MessageFactory.SiteThemeProgressEvent(directoryService.FileSystem.Path.GetFileName(theme.FileName), theme.Name,
                ProgressEventType.Ended));

        logger.LogInformation("Theme Sync complete");
    }

    /// <summary>
    /// Deletes a SiteTheme. The CSS file will be moved to temp/ to allow user to recover data
    /// </summary>
    /// <param name="siteThemeId"></param>
    /// <param name="ct"></param>
    public async Task DeleteTheme(int siteThemeId, CancellationToken ct = default)
    {
        // Validate no one else is using this theme
        var inUse = await unitOfWork.SiteThemeRepository.IsThemeInUse(siteThemeId);
        if (inUse)
        {
            throw new KavitaException("errors.delete-theme-in-use");
        }

        var siteTheme = await unitOfWork.SiteThemeRepository.GetTheme(siteThemeId);
        if (siteTheme == null) return;

        await RemoveTheme(siteTheme);
    }

    /// <summary>
    /// This assumes a file is already in temp directory and will be used for
    /// </summary>
    /// <param name="tempFile"></param>
    /// <param name="username"></param>
    /// <param name="ct"></param>
    /// <returns></returns>
    public async Task<SiteTheme> CreateThemeFromFile(string tempFile, string username, CancellationToken ct = default)
    {
        if (!directoryService.FileSystem.File.Exists(tempFile))

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Have every user using the theme switch to a different theme (or default), then retry the delete.
  2. As admin, bulk-reset affected users' theme preference to the default, then delete.
  3. Re-list themes and confirm none reference the target before deleting.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await api.delete(`/api/theme?themeId=${themeId}`);
} catch (e) {
  // HTTP 500 with raw key 'errors.delete-theme-in-use': users still have it active.
  notify('Theme is in use by at least one user. Have them switch themes first.');
}

Prevention

When it happens

Trigger: DELETE /api/theme?themeId=N while one or more AppUserPreferences rows still reference that theme as the user's Theme.

Common situations: Admin deletes a theme that the whole server or a single user has active; users who picked a custom theme never switched back to a default before the admin removes it.

Related errors


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