louthy/language-ext · error · ArgumentException

An element with the same key already exists in the Map

Error message

An element with the same key already exists in the Map

What it means

This ArgumentException is the strict branch of Set.Internal's Add helper: when a key comparing equal to an existing node's key is added and the add option is neither TryAdd nor TryUpdate, insertion cannot proceed and it throws. The faulting input is the duplicate key passed to Add<OrdK, K> without a tolerant AddOpt; it enforces key uniqueness in the AVL tree structure.

Solutions

  1. Check set.Contains(key) before adding, or use AddOrUpdate/TryAdd semantics
  2. Use the returned set from Add and rely on TryAdd where available
  3. Fix a buggy Ord comparer that collapses distinct values to equal

Example fix

// before
set = set.Add(item); // throws if present
// after
if (!set.Contains(item)) set = set.Add(item);
Defensive patterns

Strategy: validation

Validate before calling

if (set.Contains(key))
    throw new InvalidOperationException($"Item {key} already exists");
set = set.Add(key);

Try / catch

try { set = set.Add(item); }
catch (ArgumentException) { /* item already present - skip or update */ }

Prevention

When it happens

Trigger: Calling the internal Add path (e.g. via Set.add on an existing element) with a key that compares equal to an existing element under the set's ordering Ord.

Common situations: Adding items from user input or a data source without checking Contains first, or an Ord implementation that treats distinct objects as equal (comparer returning 0).

Related errors


AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15). Data as JSON: /api/errors/914de5a2bbba673e. Report an issue: GitHub.

Appendix: source

Thrown at LanguageExt.Core/Immutable Collections/Set/Internal/Set.Internal.cs:868

        else if (cmp > 0)
        {
            node.Right = Add<OrdK, K>(node.Right, key, option);
            return Balance(node);
        }
        else if (option == AddOpt.TryAdd)
        {
            // Already exists, but we don't care
            return node;
        }
        else if (option == AddOpt.TryUpdate)
        {
            // Already exists, and we want to update the content
            node.Key = key;
            return node;
        }
        else
        {
            throw new ArgumentException("An element with the same key already exists in the Map");
        }
    }

    public static SetItem<K> Balance<K>(SetItem<K> node)
    {
        node.Height = (byte)(1 + Math.Max(node.Left.Height, node.Right.Height));
        node.Count = 1 + node.Left.Count + node.Right.Count;

        return node.BalanceFactor >= 2
                   ? node.Right.BalanceFactor < 0
                         ? DblRotLeft(node)
                         : RotLeft(node)
                   : node.BalanceFactor <= -2
                       ? node.Left.BalanceFactor > 0
                             ? DblRotRight(node)
                             : RotRight(node)
                       : node;
    }

View on GitHub (pinned to 2f0e362824)