clockworklabs/SpacetimeDB · error · ArgumentException

Argument must be a ConnectionId

Error message

Argument must be a ConnectionId

What it means

The non-generic IComparable.CompareTo(object) on ConnectionId throws ArgumentException when the argument is neither a ConnectionId nor null (null sorts as greater, returning 1). This is the standard BCL pattern: object-based comparison refuses types it cannot meaningfully order.

Source

Thrown at crates/bindings-csharp/BSATN.Runtime/Builtins.cs:233

        // --- / customized ---
    }

    public override string ToString() => Util.ToHexBigEndian(value);

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

    /// <inheritdoc cref="IComparable{T}.CompareTo(T)" />
    public int CompareTo(ConnectionId connectionId) => this.value.CompareTo(connectionId.value);
}

[StructLayout(LayoutKind.Sequential)]
public readonly record struct Identity : IEquatable<Identity>, IComparable, IComparable<Identity>
{
    private readonly U256 value;

    internal Identity(U256 val) => value = val;

    /// <summary>
    /// Create an Identity from a LITTLE-ENDIAN byte array.
    ///
    /// If you are parsing an Identity from a string, you probably want FromHexString instead,

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Compare with the typed overload connId.CompareTo(otherConnectionId)
  2. Store ConnectionIds in strongly-typed collections (List<ConnectionId>, Dictionary<ConnectionId, ...>)
  3. Narrow first: if (obj is ConnectionId cid) ... else throw/handle
  4. For mixed-key maps, use the hex string form as the common comparable key

Example fix

// before
list.Sort((a, b) => ((IComparable)a).CompareTo(b)); // mixed types throw

// after
list.Sort((a, b) => (a, b) switch { (ConnectionId x, ConnectionId y) => x.CompareTo(y), _ => throw new ArgumentException("Mixed key types") });
Defensive patterns

Strategy: type-guard

Type guard

static bool IsConnectionId(object? o) => o is ConnectionId;

Prevention

When it happens

Trigger: ((IComparable)connId).CompareTo(otherBoxed); sorting or binary-searching non-generic collections (ArrayList, object[]) that contain ConnectionIds plus other values; generic-free comparison helpers passing object.

Common situations: Bridging into non-generic APIs (older reflection-based serializers, DataTable keys, COM interop); dedup/sort utilities written against object.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/28dc8aee62912ccd. Report an issue: GitHub.