clockworklabs/SpacetimeDB · error · ArgumentException

Argument must be a Identity

Error message

Argument must be a Identity

What it means

Identity is the client's 256-bit user/module identity type. Its untyped IComparable.CompareTo(object?) overload accepts only another Identity or null (null sorts after); any other runtime type throws ArgumentException.

Solutions

  1. Use the typed CompareTo(Identity) overload
  2. Pattern-match (if (o is Identity id)) before comparing boxed values
  3. Keep identity collections typed as Identity[]

Example fix

// before
int cmp = identity.CompareTo(otherObject); // ArgumentException: Argument must be a Identity

// after
if (otherObject is Identity other)
{
    int cmp = identity.CompareTo(other);
}
Defensive patterns

Strategy: type-guard

Validate before calling

static bool CanCompareWithIdentity(object? other) => other is null || other is Identity;

Type guard

static bool IsIdentity(object? value) => value is Identity;

Try / catch

try
{
    var cmp = ((IComparable)identity).CompareTo(boxed);
}
catch (ArgumentException)
{
    // convert to Identity or reject the mixed comparison
}

Prevention

When it happens

Trigger: Calling CompareTo(object?) with a boxed ConnectionId, string, U256, or other non-Identity value — via object-based sorting or comparison of identity collections.

Common situations: Ordering mixed subscriber/identity records; comparing ids deserialized as object from JSON; generic helpers that take IComparable with object arguments.

Related errors


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

Appendix: source

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

    }

    // This must be explicitly implemented, otherwise record will generate a new implementation.
    public override string ToString() => Util.ToHexBigEndian(value);

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

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

/// <summary>
/// A timestamp that represents a unique moment in time (in the Earth's reference frame).
///
/// This type may be converted to/from a DateTimeOffset, but the conversion can lose precision.
/// This type has less precision than DateTimeOffset (units of microseconds rather than units of 100ns).
/// </summary>
[StructLayout(LayoutKind.Sequential)] // we should be able to use it in FFI
public record struct Timestamp(long MicrosecondsSinceUnixEpoch)
    : IStructuralReadWrite,
        IComparable<Timestamp>
{

View on GitHub (pinned to 6dee26c6ef)