Kareadita/Kavita · error · KavitaException
errors.import-fields.non-unique-fields
errors.import-fields.non-unique-fields
Error message
errors.import-fields.non-unique-fields
What it means
Thrown by SettingsService.ImportFieldMappings when the FieldMappings list contains entries with duplicate Ids - DistinctBy(f => f.Id).Count() differs from total count. Field mappings are identified by Id, so two entries sharing an Id create an ambiguous import target.
Source
Thrown at Kavita.Services/SettingsService.cs:136
// Save changes
await unitOfWork.CommitAsync(ct);
// Return updated settings
return await unitOfWork.SettingsRepository.GetMetadataSettingDto(ct);
}
public async Task<FieldMappingsImportResultDto> ImportFieldMappings(FieldMappingsDto dto,
ImportSettingsDto settings, CancellationToken ct = default)
{
if (dto.AgeRatingMappings.Keys.Distinct().Count() != dto.AgeRatingMappings.Count)
{
throw new KavitaException("errors.import-fields.non-unique-age-ratings");
}
if (dto.FieldMappings.DistinctBy(f => f.Id).Count() != dto.FieldMappings.Count)
{
throw new KavitaException("errors.import-fields.non-unique-fields");
}
return settings.ImportMode switch
{
ImportMode.Merge => await MergeFieldMappings(dto, settings),
ImportMode.Replace => await ReplaceFieldMappings(dto, settings),
_ => throw new ArgumentOutOfRangeException(nameof(settings), $"Invalid import mode {nameof(settings.ImportMode)}")
};
}
/// <summary>
/// Will fully replace any enabled fields, always successful
/// </summary>
/// <param name="dto"></param>
/// <param name="settings"></param>
/// <returns></returns>
private async Task<FieldMappingsImportResultDto> ReplaceFieldMappings(FieldMappingsDto dto, ImportSettingsDto settings)
{View on GitHub (pinned to 9c3e540000)
Solutions
- De-duplicate FieldMappings by Id before import (keep one per Id).
- Regenerate the export from a clean current instance.
- Validate the import payload with a schema requiring unique Ids.
- When merging exports, reconcile conflicting Ids (assign new ids or drop duplicates).
Example fix
// before
await settingsService.ImportFieldMappings(dto, settings, ct);
// after - dedupe by Id
dto.FieldMappings = dto.FieldMappings
.DistinctBy(f => f.Id)
.ToList();
await settingsService.ImportFieldMappings(dto, settings, ct); Defensive patterns
Strategy: validation
Validate before calling
if (dto.FieldMappings.DistinctBy(f => f.Id).Count() != dto.FieldMappings.Count)
dto.FieldMappings = dto.FieldMappings.DistinctBy(f => f.Id).ToList();
await settingsService.ImportFieldMappings(dto, settings, ct); Type guard
static bool FieldMappingIdsUnique(IEnumerable<FieldMapping> f) => f.DistinctBy(x => x.Id).Count() == f.Count();
Prevention
- De-duplicate FieldMappings by Id before import.
- Regenerate exports from a clean instance.
- Validate import JSON requiring unique Ids.
When it happens
Trigger: Posting a FieldMappingsDto whose FieldMappings collection has two or more items with the same Id - e.g. copy-pasted rows in an export, or a merge of two exports that both contain the same mapping id.
Common situations: Exporting the same mapping twice into one file; a UI allowed adding a duplicate row; or a migration re-imported without clearing prior ids.
Related errors
- errors.import-fields.non-unique-age-ratings
- ip-address-invalid
- total-backups
- total-logs
- oidc-invalid-authority
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/788db780afc0b723.
Report an issue: GitHub.