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

  1. Delete the affected series from the Kavita UI and rescan so the volumes are rebuilt cleanly (the message's prescribed fix).
  2. Inspect the Volumes table for the seriesId and remove duplicate rows with the same LookupName, keeping one.
  3. Ensure file/folder naming is consistent so two distinct folders don't parse to the same volume number.
  4. 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

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.