{"record":{"id":"788db780afc0b723","repo":"Kareadita/Kavita","slug":"errors-import-fields-non-unique-fields","errorCode":"errors.import-fields.non-unique-fields","errorMessage":"errors.import-fields.non-unique-fields","messagePattern":"errors\\.import-fields\\.non-unique-fields","errorType":"exception","errorClass":"KavitaException","httpStatus":400,"severity":"error","filePath":"Kavita.Services/SettingsService.cs","lineNumber":136,"sourceCode":"\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>\n    /// <param name=\"dto\"></param>\n    /// <param name=\"settings\"></param>\n    /// <returns></returns>\n    private async Task<FieldMappingsImportResultDto> ReplaceFieldMappings(FieldMappingsDto dto, ImportSettingsDto settings)\n    {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Services/SettingsService.cs#L118-L154","documentation":"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.","triggerScenarios":"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.","commonSituations":"Exporting the same mapping twice into one file; a UI allowed adding a duplicate row; or a migration re-imported without clearing prior ids.","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)."],"exampleFix":"// before\nawait settingsService.ImportFieldMappings(dto, settings, ct);\n\n// after - dedupe by Id\ndto.FieldMappings = dto.FieldMappings\n    .DistinctBy(f => f.Id)\n    .ToList();\nawait settingsService.ImportFieldMappings(dto, settings, ct);","handlingStrategy":"validation","validationCode":"if (dto.FieldMappings.DistinctBy(f => f.Id).Count() != dto.FieldMappings.Count)\n    dto.FieldMappings = dto.FieldMappings.DistinctBy(f => f.Id).ToList();\nawait settingsService.ImportFieldMappings(dto, settings, ct);","typeGuard":"static bool FieldMappingIdsUnique(IEnumerable<FieldMapping> f) => f.DistinctBy(x => x.Id).Count() == f.Count();","tryCatchPattern":null,"preventionTips":["De-duplicate FieldMappings by Id before import.","Regenerate exports from a clean instance.","Validate import JSON requiring unique Ids."],"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"}