louthy/language-ext · error · ArgumentException

Key doesn't exist in map

Error message

Key doesn't exist in map: {change}

What it means

LanguageExt's TrieSet-backed set/map structures distinguish strict updates (SetItem) from lenient ones (TrySetItem). When a strict SetItem update traverses the trie and reaches a branch where the key is absent, the Entries node's Update method throws this ArgumentException instead of silently no-oping. The message interpolates the missing key; the literal '{change}' appears if the exception is inspected without formatting or the value's ToString is '{change}'.

Solutions

  1. Use TrySetItem instead of SetItem so a missing key is a harmless no-op
  2. Check containment first (e.g. set.Contains(key)) before calling SetItem
  3. If the intent is insert-or-update, use Add instead of SetItem
  4. Catch ArgumentException around the update if missing keys are expected

Example fix

// before
var set = TrieSet.create(1, 2);
var updated = set.SetItem(3); // throws ArgumentException

// after
var updated = set.TrySetItem(3); // no-op if missing, or:
if (set.Contains(3)) { var updated = set.SetItem(3); }
Defensive patterns

Strategy: validation

Validate before calling

if (set.Contains(key)) { var updated = set.SetItem(key); } else { /* handle absence */ }

Type guard

bool CanSet<T>(TrieSet<T> set, T key) => set.Contains(key);

Try / catch

try { updated = set.SetItem(key); }
catch (ArgumentException ex) when (ex.Message.Contains("Key doesn't exist")) { updated = set.TrySetItem(key); }

Prevention

When it happens

Trigger: Calling a SetItem-style update on a TrieSet-backed structure (e.g. setItem / [updateType=SetItem] via the trie root) with a key that is not currently present in the set, so traversal lands in the 'else' branch at TrieSet.cs:869 where neither EntryMap nor NodeMap contains the key's hash bit.

Common situations: Using setItem on a HashSet/TrieSet where the developer assumed the item exists; refactors that changed add to set; keys removed concurrently or between check and update; typos in key values.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at LanguageExt.Core/Immutable Collections/TrieSet/TrieSet.cs:869

                                newNodes));
                }
            }
            else if (Bit.Get(NodeMap, mask))
            {
                // var nodeIndex = Index(NodeMap, mask);
                var nodeIndex = BitCount((int)NodeMap & (((int)mask) - 1));

                var nodeToUpdate = Nodes[nodeIndex];
                var (cd, newNode) = nodeToUpdate.Update(env, change, hash, section.Next());
                var newNodes = SetItem(Nodes, nodeIndex, newNode, env.Mutate);
                return (cd, new Entries(EntryMap, NodeMap, Items, newNodes));
            }
            else
            {
                if (env.Type == UpdateType.SetItem)
                {
                    // Key must already exist to set it
                    throw new ArgumentException($"Key doesn't exist in map: {change}");
                }
                else if (env.Type == UpdateType.TrySetItem)
                {
                    // Key doesn't exist, so there's nothing to set
                    return (0, this);
                }

                // var entryIndex = Index(EntryMap, mask);
                var entryIndex = BitCount((int)EntryMap & (((int)mask) - 1));

                // var entries = Bit.Set(EntryMap, mask, true);
                var entries = EntryMap | mask;

                var newItems = Insert(Items, entryIndex, change);
                return (1, new Entries(entries, NodeMap, newItems, Nodes));
            }
        }

View on GitHub (pinned to 2f0e362824)