{"record":{"id":"a51b448ca0ee8cc2","repo":"stride3d/stride","slug":"two-elements-of-the-collection-have-the-same-id","errorCode":null,"errorMessage":"Two elements of the collection have the same id","messagePattern":"Two elements of the collection have the same id","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/Reflection/CollectionItemIdentifiers.cs","lineNumber":123,"sourceCode":"        }\n        return id;\n    }\n\n    public void MarkAsDeleted(ItemId id)\n    {\n        deletedItems.Add(id);\n    }\n\n    public void UnmarkAsDeleted(ItemId id)\n    {\n        deletedItems.Remove(id);\n    }\n\n    public void Validate(bool isList)\n    {\n        var ids = new HashSet<ItemId>(keyToIdMap.Values);\n        if (ids.Count != keyToIdMap.Count)\n            throw new InvalidOperationException(\"Two elements of the collection have the same id\");\n\n        foreach (var deleted in deletedItems)\n            ids.Add(deleted);\n\n        if (ids.Count != keyToIdMap.Count + deletedItems.Count)\n            throw new InvalidOperationException(\"An id is both marked as deleted and associated to a key of the collection.\");\n    }\n\n    public object? GetKey(ItemId itemId)\n    {\n        object? output = null;\n        // TODO: add indexing by guid to avoid O(n)\n        foreach (var kvp in keyToIdMap)\n        {\n            if (kvp.Value == itemId)\n            {\n                if(output != null)\n                    throw new InvalidOperationException(\"Two elements of the collection have the same id\");","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/Reflection/CollectionItemIdentifiers.cs#L105-L141","documentation":"Thrown by CollectionItemIdentifiers.Validate when two collection keys map to the same ItemId in keyToIdMap. Item ids must be unique per element, otherwise id-based tracking (undo/redo, serialization, diffing) becomes ambiguous, so the invariant is enforced eagerly.","triggerScenarios":"Calling Validate(isList) on a CollectionItemIdentifiers whose keyToIdMap contains duplicate ItemId values — typically after manual id assignment, deserialization of corrupted data, or code that reuses an id for two elements.","commonSituations":"Generating ids with a bad/constant source (e.g. a zeroed guid); cloning collections and copying ids instead of regenerating; hand-editing serialized asset YAML where ids were duplicated.","solutions":["Regenerate a fresh ItemId for each element instead of copying ids.","Deduplicate: scan keyToIdMap and assign a new id to any duplicate before Validate.","Rebuild the CollectionItemIdentifiers from the live collection so keys/ids are recomputed.","Fix corrupted asset/serialization data containing duplicated ItemId guids."],"exampleFix":"// before\nforeach (var k in identifiers.Keys)\n    identifiers[k] = fixedId; // duplicate ids\n// after\nforeach (var k in identifiers.Keys)\n    identifiers[k] = ItemId.New(); // unique per element","handlingStrategy":"validation","validationCode":"var idSet = new HashSet<ItemId>();\nforeach (var key in identifiers.Keys)\n{\n    if (!idSet.Add(identifiers[key]))\n        identifiers[key] = ItemId.New(); // regenerate duplicates\n}\nidentifiers.Validate(isList);","typeGuard":null,"tryCatchPattern":"try { identifiers.Validate(isList); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"same id\"))\n{\n    // rebuild or deduplicate ids, then re-validate\n}","preventionTips":["Always generate ids with ItemId.New(), never copy them.","When cloning collections, regenerate ids for the clone.","Never hard-code or default ItemId values.","Validate ids after deserialization before further mutation."],"tags":["invariant","collections","item-ids"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}