stride3d/stride · error · InvalidOperationException

An item with the same key has already been added.

Error message

An item with the same key has already been added.

What it means

KeyedSortedList derives a key from each item via GetKeyForItem and uses BinarySearch to keep items sorted. If BinarySearch finds the exact key (index >= 0), the key already exists and Add throws InvalidOperationException; it never inserts duplicates. Callers must remove the old item or use the indexer to replace it.

Solutions

  1. Check ContainsKey(GetKeyForItem(item)) before Add, or remove the old item first
  2. Replace via the indexer: list[index] = item after locating the existing entry
  3. Review GetKeyForItem to ensure it returns a truly unique key per item
  4. Catch InvalidOperationException around Add if duplicates are expected and handle them (e.g. skip or update)

Example fix

// before
sortedList.Add(updatedEntity); // throws: same key exists
// after
int i = sortedList.IndexOf(updatedEntity);
if (i >= 0) sortedList[i] = updatedEntity; else sortedList.Add(updatedEntity);
Defensive patterns

Strategy: validation

Validate before calling

if (!list.ContainsKey(key)) list.Add(item);

Try / catch

try { list.Add(item); } catch (InvalidOperationException) { /* update or skip duplicate */ }

Prevention

When it happens

Trigger: Adding an item whose GetKeyForItem value equals the key of an item already in the list, e.g. list.Add(newItem) where an item with the same key was added earlier in the same session.

Common situations: Re-adding an updated entity (same key, new values) without removing the old one; loading the same entity twice from persistence; a key function (GetKeyForItem override) that returns identical keys for distinct items by mistake.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/2db2aec8602d0a65. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core/Collections/KeyedSortedList.cs:71

        items.RemoveAt(index);
    }

    /// <summary>
    /// Sorts again this list (in case keys were mutated).
    /// </summary>
    public void Sort()
    {
        Array.Sort(items.Items, 0, items.Count, new Comparer(this));
    }

    /// <inheritdoc/>
    public void Add(T item)
    {
        var key = GetKeyForItem(item);

        var index = BinarySearch(key);
        if (index >= 0)
            throw new InvalidOperationException("An item with the same key has already been added.");

        InsertItem(~index, item);
    }

    public bool ContainsKey(TKey key)
    {
        return BinarySearch(key) >= 0;
    }

    public bool Remove(TKey key)
    {
        var index = BinarySearch(key);
        if (index < 0)
            return false;

        RemoveItem(index);

        return true;

View on GitHub (pinned to 96fad776d2)