Kareadita/Kavita · error · OpdsException

smart-filter-doesnt-exist

Error message

smart-filter-doesnt-exist

What it means

Thrown by OpdsService.ResolveSmartFilter when a smart filter with the given EntityId cannot be found in the database (AppUserSmartFilterRepository.GetById returns null). This indicates the OPDS client requested a smart filter feed using an ID that does not correspond to any stored AppUserSmartFilter record. The error message is localized via the LocalizationService for the requesting user.

Source

Thrown at Kavita.Services/OpdsService.cs:394

        return feed;
    }

    /// <summary>
    /// Returns the Entities matching this smart filter.
    /// </summary>
    /// <param name="request"></param>
    /// <param name="ct"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    public async Task<Feed> ResolveSmartFilter(OpdsItemsFromEntityIdRequest request, CancellationToken ct = default)
    {
        var userId = UnpackRequest(request, out var apiKey, out var prefix, out var baseUrl);

        var filter = await unitOfWork.AppUserSmartFilterRepository.GetById(request.EntityId, ct);
        if (filter == null)
        {
            throw new OpdsException(await localizationService.TranslateAsync(userId, "smart-filter-doesnt-exist"));
        }

        var feed = CreateFeed(await localizationService.TranslateAsync(userId, "smartFilters-" + filter.Id), $"{apiKey}/smart-filters/{filter.Id}/", apiKey, prefix);
        SetFeedId(feed, "smartFilters-" + filter.Id);

        var decodedFilter = SmartFilterHelper.Decode(filter.Filter);
        var userParams = GetUserParams(request.PageNumber);


        switch (decodedFilter.EntityType)
        {
            case FilterEntityType.Series:
                var series = await unitOfWork.SeriesRepository.GetSeriesDtoForLibraryIdAsync(userId, userParams,
                    (SeriesFilterV2Dto) decodedFilter, ct: ct);
                var seriesMetadatas = await unitOfWork.SeriesRepository.GetSeriesMetadataForIdsAsync(series.Select(s => s.Id), ct);

                foreach (var seriesDto in series)
                {

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Have the user refresh their smart filter list in the OPDS client to obtain current valid filter IDs.
  2. Verify the filterId in the OPDS URL matches an existing smart filter in the user's Kavita dashboard.
  3. If the filter was deleted, recreate it or remove the bookmark from the OPDS reader.
  4. Ensure the correct user's API key is being used; smart filters are user-scoped.
  5. Check Kavita's admin panel or database (AppUserSmartFilters table) to confirm which filter IDs exist.

Example fix

// No code fix — this is a stale/deleted resource reference.
// In the OPDS client, navigate back to the root feed and
// re-select the smart filter to get a fresh URL.
// If developing an OPDS client, validate the ID first:

// GET /api/opds/{apiKey}/smart-filters/  -> list all valid filter IDs
// then only use IDs returned in that list.
Defensive patterns

Strategy: validation

Validate before calling

// Before requesting a smart filter feed, verify it exists:
// var filter = await unitOfWork.AppUserSmartFilterRepository.GetById(filterId, ct);
// if (filter == null)
// {
//     ShowUser("This smart filter no longer exists.");
//     return;
// }
// var feed = await opdsService.ResolveSmartFilter(request, ct);

Try / catch

// try { var feed = await opdsService.ResolveSmartFilter(request, ct); }
// catch (OpdsException ex)
// {
//     if (ex.Message.Contains("smart-filter-doesnt-exist"))
//     {
//         // Refresh the smart-filter list; the cached ID is stale.
//         await RefreshSmartFilterList();
//         return BadRequest("Smart filter not found. Please refresh.");
//     }
//     return BadRequest(ex.Message);
// }

Prevention

When it happens

Trigger: An OPDS client sends a GET request to {apiKey}/smart-filters/{filterId}. The filterId in the URL maps to request.EntityId. The repository lookup returns null because the filter was deleted, the ID is wrong, or the filter belongs to a different user (if GetById is user-scoped).

Common situations: A user deleted a smart filter in the Kavita web UI but their OPDS reader app cached the old feed URL. The OPDS client is using a stale bookmark or cached link. The filterId was mistyped or corrupted in the URL. A different user's API key is being used to access another user's filter.

Related errors


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