egametang/ET · error · ArgumentException

SortedSet_LowerValueGreaterThanUpperValue

Error message

SortedSet_LowerValueGreaterThanUpperValue

What it means

Thrown by SortedSet<T>.GetViewBetween(T lowerValue, T upperValue) when the comparer reports lowerValue as strictly greater than upperValue. The library enforces the contract that the view's lower bound must not exceed its upper bound, because a backwards range cannot map to any subtree. It surfaces as an ArgumentException on the lowerValue parameter.

Source

Thrown at Packages/cn.etetet.core/Scripts/Core/Share/Collection/SortedSet.cs:1666

                return current.Item;
            }
        }

        public IEnumerable<T> Reverse()
        {
            Enumerator e = new Enumerator(this, reverse: true);
            while (e.MoveNext())
            {
                yield return e.Current;
            }
        }

        public virtual SortedSet<T> GetViewBetween(T lowerValue, T upperValue)
        {
            if (Comparer.Compare(lowerValue, upperValue) > 0)
            {
                throw new ArgumentException(SR.SortedSet_LowerValueGreaterThanUpperValue, nameof(lowerValue));
            }
            return new TreeSubSet(this, lowerValue, upperValue, true, true);
        }

#if DEBUG
        /// <summary>
        /// debug status to be checked whenever any operation is called
        /// </summary>
        /// <returns></returns>
        internal virtual bool versionUpToDate()
        {
            return true;
        }
#endif

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) => GetObjectData(info, context);

        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Validate (or swap) bounds before calling: if (Comparer.Compare(lo, hi) > 0) (lo, hi) = (hi, lo);
  2. Check that your custom IComparer<T>.Compare returns 0 for equal items and a consistent ordering.
  3. Unit-test GetViewBetween with lo == hi (allowed) and lo > hi (must throw) to lock the contract.

Example fix

// before
var view = set.GetViewBetween(max, min); // throws if max > min

// after
if (set.Comparer.Compare(min, max) > 0) (min, max) = (max, min);
var view = set.GetViewBetween(min, max);
Defensive patterns

Strategy: validation

Validate before calling

// Validate before GetViewBetween
T lo = min, hi = max;
if (set.Comparer.Compare(lo, hi) > 0) (lo, hi) = (hi, lo);
var view = set.GetViewBetween(lo, hi);

Prevention

When it happens

Trigger: Calling GetViewBetween(a, b) where Comparer.Compare(a, b) > 0; e.g. GetViewBetween(10, 5) with the default int comparer, or passing arguments in the wrong order. Also triggered by a custom IComparer<T> whose Compare returns an unexpected sign for equal or inverted inputs.

Common situations: Swapping min/max arguments by mistake; building bounds from user/sorted input that is not pre-validated; using a reverse or culture-specific comparer where the order surprises the caller; off-by-one when deriving bounds from an index.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/5f39f189ed4fc076. Report an issue: GitHub.