Kareadita/Kavita · critical · KavitaException
Kavita found corrupted volume entries on {series.Name}. Plea
Error message
Kavita found corrupted volume entries on {series.Name}. Please delete the series from Kavita via UI and rescan What it means
Thrown by ProcessSeries.UpdateVolumes when series.Volumes.SingleOrDefault(LookupName == volumeNumber) throws 'Sequence contains more than one matching element' - i.e. the database has two or more Volume rows for the same series with the same LookupName. This is data corruption: the scanner cannot decide which volume to update, so it aborts the scan for that series and asks the user to delete and rescan.
Source
Thrown at Kavita.Services/Scanner/ProcessSeries.cs:684
private async Task UpdateVolumes(Dictionary<string, Person> databasePeople, MetadataSettingsDto settings, Series series, IList<ParserInfo> parsedInfos, bool forceUpdate = false)
{
// Add new volumes and update chapters per volume
var distinctVolumes = parsedInfos.DistinctVolumes();
foreach (var volumeNumber in distinctVolumes)
{
Volume? volume;
try
{
// With the Name change to be formatted, Name no longer working because Name returns "1" and volumeNumber is "1.0", so we use LookupName as the original
volume = series.Volumes.SingleOrDefault(s => s.LookupName == volumeNumber);
}
catch (Exception ex)
{
// TODO: Push this to UI in some way
if (!ex.Message.Equals("Sequence contains more than one matching element")) throw;
logger.LogCritical(ex, "[ScannerService] Kavita found corrupted volume entries on {SeriesName}. Please delete the series from Kavita via UI and rescan", series.Name);
throw new KavitaException(
$"Kavita found corrupted volume entries on {series.Name}. Please delete the series from Kavita via UI and rescan");
}
if (volume == null)
{
volume = new VolumeBuilder(volumeNumber)
.WithSeriesId(series.Id)
.Build();
series.Volumes.Add(volume);
}
volume.LookupName = volumeNumber;
volume.Name = volume.GetNumberTitle();
var infos = parsedInfos.Where(p => p.Volumes == volumeNumber).ToArray();
await UpdateChapters(new UpdateChapterArgs
{
Settings = settings,View on GitHub (pinned to 9c3e540000)
Solutions
- Delete the affected series from the Kavita UI and rescan so the volumes are rebuilt cleanly (the message's prescribed fix).
- Inspect the Volumes table for the seriesId and remove duplicate rows with the same LookupName, keeping one.
- Ensure file/folder naming is consistent so two distinct folders don't parse to the same volume number.
- Run the scan to completion without interruption; avoid killing Kavita mid-scan.
Example fix
// before - data corruption causes the throw mid-scan
volume = series.Volumes.SingleOrDefault(s => s.LookupName == volumeNumber);
// after - heal duplicates before scanning
var dups = series.Volumes.Where(v => v.LookupName == volumeNumber).ToList();
if (dups.Count > 1)
{
// merge chapters into the first, remove the rest, then re-scan
var keep = dups[0];
foreach (var extra in dups.Skip(1)) { keep.Chapters.AddRange(extra.Chapters); series.Volumes.Remove(extra); }
} Defensive patterns
Strategy: validation
Validate before calling
var dups = series.Volumes.GroupBy(v => v.LookupName).Where(g => g.Count() > 1).ToList();
if (dups.Any()) { /* heal or abort before scanning */ return BadRequest("Duplicate volumes detected, rescan needed"); } Type guard
static bool VolumesAreUnique(Series s) => s.Volumes.GroupBy(v => v.LookupName).All(g => g.Count() == 1);
Try / catch
try { await scannerService.ScanSeries(seriesId); }
catch (KavitaException ex) when (ex.Message.Contains("corrupted volume entries"))
{ await adminService.DeleteAndRescan(seriesId); } Prevention
- Avoid interrupting scans mid-way.
- Keep folder/file naming consistent so two folders don't parse to the same volume.
- Periodically audit for duplicate Volume rows by LookupName.
- Don't hand-edit the Volumes table.
When it happens
Trigger: During a library scan, UpdateVolumes iterates distinct parsed volume numbers and the SingleOrDefault lookup matches multiple Volume entities sharing the same LookupName for one series - usually from a prior partial scan, a crashed migration, or a manual DB edit.
Common situations: An interrupted scan left duplicate volume rows; a migration changed LookupName semantics and created dupes; files were renamed so two folders now parse to the same volume number but old rows weren't cleaned; or a manual SQLite edit inserted a duplicate.
Related errors
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/b4d6f9181158180a.
Report an issue: GitHub.