Kareadita/Kavita · warning · KavitaException

smart-filter-doesnt-exist

smart-filter-doesnt-exist

Error message

smart-filter-doesnt-exist

What it means

Thrown by StreamService.CreateDashboardStreamFromSmartFilter when AppUserSmartFilterRepository.GetById(smartFilterId) returns null — the smart filter does not exist (or does not belong to the user). The message is translated to 'Smart Filter doesn't exist'. StreamController.AddDashboard does not catch it, so it surfaces via ExceptionMiddleware as HTTP 500 with that text.

Source

Thrown at Kavita.Services/StreamService.cs:53

    public async Task<IEnumerable<SideNavStreamDto>> GetSidenavStreams(int userId, bool visibleOnly = true, CancellationToken ct = default)
    {
        return await unitOfWork.UserRepository.GetSideNavStreams(userId, visibleOnly, ct);
    }

    public async Task<IEnumerable<ExternalSourceDto>> GetExternalSources(int userId, CancellationToken ct = default)
    {
        return await unitOfWork.AppUserExternalSourceRepository.GetExternalSources(userId, ct);
    }

    public async Task<DashboardStreamDto> CreateDashboardStreamFromSmartFilter(int userId, int smartFilterId,
        CancellationToken ct = default)
    {
        var user = await unitOfWork.UserRepository.GetUserByIdAsync(userId, AppUserIncludes.DashboardStreams, ct);
        if (user == null) throw new KavitaException(await localizationService.TranslateAsync(userId, "no-user"));

        var smartFilter = await unitOfWork.AppUserSmartFilterRepository.GetById(smartFilterId, ct);
        if (smartFilter == null) throw new KavitaException(await localizationService.TranslateAsync(userId, "smart-filter-doesnt-exist"));

        var stream = user.DashboardStreams.FirstOrDefault(d => d.SmartFilter?.Id == smartFilterId);
        if (stream != null) throw new KavitaException(await localizationService.TranslateAsync(userId, "smart-filter-already-in-use"));

        var maxOrder = user!.DashboardStreams.Max(d => d.Order);
        var createdStream = new AppUserDashboardStream()
        {
            Name = smartFilter.Name,
            IsProvided = false,
            StreamType = DashboardStreamType.SmartFilter,
            Visible = true,
            Order = maxOrder + 1,
            SmartFilter = smartFilter
        };

        user.DashboardStreams.Add(createdStream);
        unitOfWork.UserRepository.Update(user);
        await unitOfWork.CommitAsync(ct);

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Use a smartFilterId from the user's current smart-filter list.
  2. Refresh the smart filters in the UI before offering 'add to dashboard'.
  3. If the filter was deleted, recreate it, then add the stream.
Defensive patterns

Strategy: validation

Validate before calling

const filters = await api.getSmartFilters();
if (!filters.some(f => f.id === smartFilterId)) {
  showError('Smart Filter not found');
  return;
}
await api.post(`/api/stream/add-dashboard-stream?smartFilterId=${smartFilterId}`);

Type guard

function isKnownFilterId(id: number, filters: { id: number }[]): boolean {
  return filters.some(f => f.id === id);
}

Prevention

When it happens

Trigger: POST /api/stream/add-dashboard-stream?smartFilterId=N with a deleted, invalid, or other-user smart filter id.

Common situations: Stale smartFilterId cached in the UI after the filter was deleted; deep link/bookmark with an old id; cross-user id confusion.

Related errors


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