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.
Solutions
- Have the user refresh their smart filter list in the OPDS client to obtain current valid filter IDs.
- Verify the filterId in the OPDS URL matches an existing smart filter in the user's Kavita dashboard.
- If the filter was deleted, recreate it or remove the bookmark from the OPDS reader.
- Ensure the correct user's API key is being used; smart filters are user-scoped.
- 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
- In OPDS clients, always navigate from the live smart-filter feed rather than using cached URLs.
- Refresh the OPDS feed after creating, editing, or deleting smart filters in the Kavita UI.
- Use the correct user's API key; smart filters are user-scoped.
- When building OPDS clients, handle 'smart-filter-doesnt-exist' by refreshing the filter list.
- Avoid hardcoding smart filter IDs in bookmarks or scripts.
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
- chapter-doesnt-exist
- series-doesnt-exist
- volume-doesnt-exist
- collection-doesnt-exist
- OPDS feed generation is not implemented for Annotation…
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/ea972081a6c9ac9a.
Report an issue: GitHub.
Appendix: 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)