clockworklabs/SpacetimeDB · error · ArgumentException

Argument must be a I128

Error message

Argument must be a I128

What it means

I128 is the SpacetimeDB BSATN.Runtime 128-bit signed integer type. It implements IComparable, and the untyped CompareTo(object?) overload only accepts another I128 (or null, which sorts after). Passing any other type throws ArgumentException because an I128 cannot be meaningfully ordered against an unrelated value.

Solutions

  1. Use the typed CompareTo(I128) overload or the <, >, == operators instead of the object-based overload
  2. Pattern-match and convert before comparing: if (other is I128 i) ... else convert explicitly
  3. When sorting mixed data, homogenize the array to I128[] first or supply a custom IComparer<object>

Example fix

// before
I128 a = GetAmount();
object other = 42L;
int cmp = a.CompareTo(other); // ArgumentException: Argument must be a I128

// after
if (other is I128 other128)
{
    int cmp = a.CompareTo(other128);
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Only invoke the untyped CompareTo when the boxed value is compatible
static bool CanCompareWithI128(object? other) => other is null || other is SpacetimeDB.I128;

Type guard

static bool IsI128(object? value) => value is SpacetimeDB.I128;

Try / catch

try
{
    var cmp = ((IComparable)i128Value).CompareTo(boxed);
}
catch (ArgumentException)
{
    // heterogeneous comparison: convert the operand to I128 or sort by type name instead
}

Prevention

When it happens

Trigger: Invoking ((IComparable)i128).CompareTo(obj) where the boxed argument is a long, decimal, I256, string, or any non-I128 type. Typical entry points: Array.Sort on an object[], ArrayList ordering, or comparing values deserialized as object.

Common situations: Sorting or searching heterogeneous collections; porting code that compared BigInteger or decimal against 128-bit ids; dynamic/object round-trips through JSON or old collection APIs.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/1b63ead3ea6bb60d. Report an issue: GitHub.

Appendix: source

Thrown at crates/bindings-csharp/BSATN.Runtime/BSATN/I128.cs:49

    internal ulong Lower => _lower;

    internal ulong Upper => _upper;

    /// <inheritdoc cref="IComparable.CompareTo(object)" />
    public int CompareTo(object? value)
    {
        if (value is I128 other)
        {
            return CompareTo(other);
        }
        else if (value is null)
        {
            return 1;
        }
        else
        {
            throw new ArgumentException("Argument must be a I128", nameof(value));
        }
    }

    /// <inheritdoc cref="IComparable{T}.CompareTo(T)" />
    public int CompareTo(I128 value)
    {
        if (this < value)
        {
            return -1;
        }
        else if (this > value)
        {
            return 1;
        }
        else
        {
            return 0;
        }

View on GitHub (pinned to 6dee26c6ef)