{"record":{"id":"17169d2fbf761958","repo":"Kareadita/Kavita","slug":"errors-import-fields-non-unique-age-ratings","errorCode":"errors.import-fields.non-unique-age-ratings","errorMessage":"errors.import-fields.non-unique-age-ratings","messagePattern":"errors\\.import-fields\\.non-unique-age-ratings","errorType":"exception","errorClass":"KavitaException","httpStatus":400,"severity":"error","filePath":"Kavita.Services/SettingsService.cs","lineNumber":131,"sourceCode":"                    DestinationValue = mappingDto.DestinationValue,\n                    ExcludeFromSource = mappingDto.ExcludeFromSource\n                });\n            }\n        }\n\n        // Save changes\n        await unitOfWork.CommitAsync(ct);\n\n        // Return updated settings\n        return await unitOfWork.SettingsRepository.GetMetadataSettingDto(ct);\n    }\n\n    public async Task<FieldMappingsImportResultDto> ImportFieldMappings(FieldMappingsDto dto,\n        ImportSettingsDto settings, CancellationToken ct = default)\n    {\n        if (dto.AgeRatingMappings.Keys.Distinct().Count() != dto.AgeRatingMappings.Count)\n        {\n            throw new KavitaException(\"errors.import-fields.non-unique-age-ratings\");\n        }\n\n        if (dto.FieldMappings.DistinctBy(f => f.Id).Count() != dto.FieldMappings.Count)\n        {\n            throw new KavitaException(\"errors.import-fields.non-unique-fields\");\n        }\n\n        return settings.ImportMode switch\n        {\n            ImportMode.Merge => await MergeFieldMappings(dto, settings),\n            ImportMode.Replace => await ReplaceFieldMappings(dto, settings),\n            _ => throw new ArgumentOutOfRangeException(nameof(settings), $\"Invalid import mode {nameof(settings.ImportMode)}\")\n        };\n    }\n\n    /// <summary>\n    /// Will fully replace any enabled fields, always successful\n    /// </summary>","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Services/SettingsService.cs#L113-L149","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait settingsService.ImportFieldMappings(dto, settings, ct);\n\n// after - dedupe before import\ndto.AgeRatingMappings = dto.AgeRatingMappings\n    .GroupBy(kvp => kvp.Key)\n    .ToDictionary(g => g.Key, g => g.Last().Value);\nawait settingsService.ImportFieldMappings(dto, settings, ct);","handlingStrategy":"validation","validationCode":"if (dto.AgeRatingMappings.Keys.Distinct().Count() != dto.AgeRatingMappings.Count)\n{\n    dto.AgeRatingMappings = dto.AgeRatingMappings\n        .GroupBy(kvp => kvp.Key).ToDictionary(g => g.Key, g => g.Last().Value);\n}\nawait settingsService.ImportFieldMappings(dto, settings, ct);","typeGuard":"static bool AgeRatingKeysUnique(Dictionary<string,string> m) => m.Keys.Distinct().Count() == m.Count;","tryCatchPattern":null,"preventionTips":["De-duplicate AgeRatingMappings by key before import.","Regenerate exports from a current instance.","Validate import JSON against a schema forbidding duplicate keys."],"tags":["settings","validation","import","metadata-mappings"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}