louthy/language-ext · error · ArgumentException
Index outside the bounds of the list
Error message
Index outside the bounds of the list
What it means
ListModule.SetItem (the AVL tree worker behind LstInternal.SetItem) throws ArgumentException('Index outside the bounds of the list') when it descends to an empty node while seeking the target index. This is a defensive internal invariant check: the public SetItem normally rejects bad indices first, so reaching it means the index equaled or exceeded the subtree count during recursion.
Solutions
- Always go through Lst/LstInternal.SetItem and validate index against the same instance you mutate.
- Ensure index is in 0..Count-1 for the exact snapshot being updated.
- Avoid calling ListModule.SetItem directly; treat it as internal API.
- Audit async workflows so an index computed from one snapshot is never applied to another.
Example fix
// before var node = ListModule.SetItem(root, value, i); // i may exceed root.Count // after if (i < 0 || i >= root.Count) throw new ArgumentOutOfRangeException(nameof(i)); var node = ListModule.SetItem(root, value, i);
Defensive patterns
Strategy: validation
Validate before calling
if (i < 0 || i >= root.Count)
throw new ArgumentOutOfRangeException(nameof(i));
var node = ListModule.SetItem(root, value, i); Try / catch
try { var node = ListModule.SetItem(root, value, i); }
catch (ArgumentException ex) when (ex.Message.Contains("Index outside"))
{
// index did not exist in this tree snapshot
} Prevention
- Avoid ListModule internals; use Lst/LstInternal public APIs that pre-validate.
- Ensure the index is validated against the same Root snapshot passed down.
- In async code, never carry an index from one immutable snapshot into another.
- Add assertions that 0 <= index < node.Count before tree recursion in custom extensions.
When it happens
Trigger: SetItem with index >= Root.Count that bypasses the public guard (e.g. a stale Root where the index was valid for an earlier snapshot); direct ListModule.SetItem calls with an out-of-range index; index == node.Left.Count is the only 'replace' position, anything larger falls into the empty-node path.
Common situations: Race-like inconsistencies from mixing list snapshots in async code; custom code invoking ListModule internals; passing indices derived from a different collection.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- IndexOutOfRangeException
- ArgumentNullException
- ArgumentOutOfRangeException
- InvalidOperationException
- Ord attribute should have a struct type that derives from…
AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15).
Data as JSON: /api/errors/9a83c6547907d989.
Report an issue: GitHub.
Appendix: source
Thrown at LanguageExt.Core/Immutable Collections/List/Internal/Lst.Internal.cs:761
{
return Balance(Make(node.Key, Insert(node.Left, key, index), node.Right));
}
else
{
return Balance(Make(node.Key, node.Left, Insert(node.Right, key, index - node.Left.Count - 1)));
}
}
public static ListItem<A> Add<A>(ListItem<A> node, A key) =>
node.IsEmpty
? new ListItem<A>(1, 1, ListItem<A>.Empty, key, ListItem<A>.Empty)
: Balance(Make(node.Key, node.Left, Add(node.Right, key)));
public static ListItem<A> SetItem<A>(ListItem<A> node, A key, int index)
{
if (node.IsEmpty)
{
throw new ArgumentException("Index outside the bounds of the list");
}
if (index == node.Left.Count)
{
return new ListItem<A>(node.Height, node.Count, node.Left, key, node.Right);
}
else if (index < node.Left.Count)
{
return new ListItem<A>(node.Height, node.Count, SetItem(node.Left, key, index), node.Key, node.Right);
}
else
{
return new ListItem<A>(node.Height, node.Count, node.Left, node.Key, SetItem(node.Right, key, index - node.Left.Count - 1));
}
}
public static T GetItem<T>(ListItem<T> node, int index)
{View on GitHub (pinned to 2f0e362824)