Kareadita/Kavita · error · KavitaException
errors.import-fields.non-unique-age-ratings
errors.import-fields.non-unique-age-ratings
Error message
errors.import-fields.non-unique-age-ratings
What it means
Thrown by SettingsService.ImportFieldMappings when the AgeRatingMappings dictionary has duplicate keys - detected because the count of distinct keys differs from the total entry count. Since AgeRatingMappings is a dictionary keyed by rating, duplicates indicate the import payload is malformed (the same rating mapped twice with conflicting values).
Source
Thrown at Kavita.Services/SettingsService.cs:131
DestinationValue = mappingDto.DestinationValue,
ExcludeFromSource = mappingDto.ExcludeFromSource
});
}
}
// 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>View on GitHub (pinned to 9c3e540000)
Solutions
- De-duplicate AgeRatingMappings by key before submitting (keep the last value per key).
- Regenerate the export from a current Kavita instance so keys are unique.
- Validate the import JSON with a schema that forbids duplicate age-rating keys.
- If merging two exports, union keys client-side first.
Example fix
// before
await settingsService.ImportFieldMappings(dto, settings, ct);
// after - dedupe before import
dto.AgeRatingMappings = dto.AgeRatingMappings
.GroupBy(kvp => kvp.Key)
.ToDictionary(g => g.Key, g => g.Last().Value);
await settingsService.ImportFieldMappings(dto, settings, ct); Defensive patterns
Strategy: validation
Validate before calling
if (dto.AgeRatingMappings.Keys.Distinct().Count() != dto.AgeRatingMappings.Count)
{
dto.AgeRatingMappings = dto.AgeRatingMappings
.GroupBy(kvp => kvp.Key).ToDictionary(g => g.Key, g => g.Last().Value);
}
await settingsService.ImportFieldMappings(dto, settings, ct); Type guard
static bool AgeRatingKeysUnique(Dictionary<string,string> m) => m.Keys.Distinct().Count() == m.Count;
Prevention
- De-duplicate AgeRatingMappings by key before import.
- Regenerate exports from a current instance.
- Validate import JSON against a schema forbidding duplicate keys.
When it happens
Trigger: Posting a FieldMappingsDto where AgeRatingMappings.Keys.Distinct().Count() != AgeRatingMappings.Count - i.e. the serialized mapping contains the same age-rating key more than once, which JSON deserialization into a Dictionary can produce from certain malformed imports.
Common situations: Hand-edited or older export JSON that repeats a rating key; a migration script merged mappings without deduping; or a UI builder emitted the same rating twice.
Related errors
- errors.import-fields.non-unique-fields
- 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/17169d2fbf761958.
Report an issue: GitHub.