Kareadita/Kavita · error · KavitaException
generic-error
Error message
generic-error
What it means
Thrown by GetEstimateToCompletionForChapter when either the series DTO or chapter DTO lookup returns null. The message is the localized 'generic-error' ('Something went wrong, please try again') resolved per-user via localizationService.TranslateAsync. It is a catch-all guard before computing reading-time estimates.
Source
Thrown at Kavita.Services/Reading/ReaderService.cs:611
{
if (next)
{
return chapter.Id;
}
var chapterNum = accessor(chapter);
if (currentChapterNumber.Equals(chapterNum)) next = true;
}
return -1;
}
public async Task<HourEstimateRangeDto> GetEstimateToCompletionForChapter(int userId, int seriesId, int chapterId)
{
var series = await unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
var chapter = await unitOfWork.ChapterRepository.GetChapterDtoAsync(chapterId, userId);
if (series == null || chapter == null)
throw new KavitaException(await localizationService.TranslateAsync(userId, "generic-error"));
if (series.Format == MangaFormat.Epub)
{
// Get the word counts for all the pages
var pageCounts = await bookService.GetWordCountsPerPage(chapter.Files.First().FilePath); // TODO: Cache
if (pageCounts == null) return GetTimeEstimate(chapter.WordCount, 0, true);
// Sum character counts for unread pages
var toReadCharacters = pageCounts
.Where(kvp => kvp.Key > chapter.PagesRead)
.Sum(kvp => kvp.Value);
var wordsLeft = WordCountAnalyzerService.GetWordCount(toReadCharacters);
return GetTimeEstimate(wordsLeft, 0, true);
}
var pagesLeft = chapter.Pages - chapter.PagesRead;
View on GitHub (pinned to 9c3e540000)
Solutions
- Verify seriesId and chapterId are valid and accessible to the user before requesting the estimate.
- Refresh the series/chapter data in the client after a library scan.
- If the error is unexpected, check logs for which of series/chapter was null and re-import the missing entity.
Defensive patterns
Strategy: validation
Validate before calling
var series = await unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId); var chapter = await unitOfWork.ChapterRepository.GetChapterDtoAsync(chapterId, userId); if (series == null || chapter == null) return null; // nothing to estimate return await readerService.GetEstimateToCompletionForChapter(userId, seriesId, chapterId);
Type guard
public static bool ResolvesBoth(SeriesDto? s, ChapterDto? c) => s is not null && c is not null;
Try / catch
try { return await readerService.GetEstimateToCompletionForChapter(userId, seriesId, chapterId); }
catch (KavitaException) { return null; // estimate unavailable, degrade gracefully } Prevention
- Verify seriesId and chapterId resolve for the user before requesting estimates.
- Treat the estimate as optional UI metadata so a null/error doesn't block reading.
- Refresh client chapter data after structural library changes.
When it happens
Trigger: Estimate endpoint called with a seriesId or chapterId that does not resolve (deleted, no access, stale id), or the chapter does not belong to the series/user.
Common situations: UI requests a time-to-complete estimate for a chapter that was just removed by a rescan; a stale chapter id cached in the client; user lacks access to the series' library.
Related errors
- series-doesnt-exist
- library-doesnt-exist
- client-device-doesnt-exist
- collection-doesnt-exist
- device-not-created
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/f6a922dd11c1ffb1.
Report an issue: GitHub.