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
- Use TrySetItem instead of SetItem so a missing key is a harmless no-op
- Check containment first (e.g. set.Contains(key)) before calling SetItem
- If the intent is insert-or-update, use Add instead of SetItem
- 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
- Prefer TrySetItem when key presence is uncertain
- Treat SetItem as a strict replace-only operation
- Use Contains checks before strict updates
- Deduplicate or validate keys before bulk updates
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
- Ord attribute should have a struct type that derives from…
- Hashable attribute should have a struct type that derives…
- Don't use Equals - use either RecordType
- Don't use Equals - use either RecordType
- s
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)