louthy/language-ext · error · ArgumentException

must be of type Mass

Error message

must be of type Mass

What it means

Mass.CompareTo(object?) throws ArgumentException "must be of type Mass" when given a non-null object that is not a Mass. Mass implements IComparable by checking `obj is Mass`; anything else fails. This is a runtime guard for the non-generic IComparable contract, which cannot be enforced at compile time.

Solutions

  1. Construct a Mass from raw values first (e.g. Mass from kilograms) and compare Mass to Mass.
  2. Use the generic CompareTo(Mass) overload or OrderBy(m => m.Kilograms).
  3. Add an `is Mass` check before the comparison and handle mismatches explicitly.
  4. Use generic collections so the typed comparer is invoked.

Example fix

// before
if (((IComparable)mass).CompareTo(rawKg) > 0) ... // ArgumentException
// after
var other = new Mass(Convert.ToDouble(rawKg));
if (mass.CompareTo(other) > 0) ...
Defensive patterns

Strategy: type-guard

Validate before calling

if (obj is null || obj is Mass) { /* safe to compare */ }

Type guard

static bool IsComparableMass(object? obj) => obj is null or Mass;

Try / catch

try { r = ((IComparable)mass).CompareTo(obj); }
catch (ArgumentException ex) when (ex.Message.Contains("must be of type Mass")) { /* handle mismatch */ }

Prevention

When it happens

Trigger: mass.CompareTo("3 kg"), mass.CompareTo(kilogramsAsDouble), or non-generic sort/comparer paths delivering boxed non-Mass values to CompareTo(object).

Common situations: Parsing raw config/DB strings into weights but forgetting to construct a Mass; non-generic collections storing mixed types; comparing Mass against other LanguageExt unit structs.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15). Data as JSON: /api/errors/1d5bef9fbb951bb3. Report an issue: GitHub.

Appendix: source

Thrown at LanguageExt.Core/Units of Measure/Mass.cs:21

namespace LanguageExt;

public readonly struct Mass : 
    IComparable<Mass>, 
    IEquatable<Mass>, 
    IComparable
{
    readonly double Value;

    internal Mass(double value) =>
        Value = value;

    public override string ToString() =>
        Kilograms + " kg";

    public int CompareTo(object? obj) =>
        obj is null         ? 1
        : obj is Mass other ? CompareTo(other)
                              : throw new ArgumentException($"must be of type {nameof(Mass)}");

    public int CompareTo(Mass other) =>
        Kilograms.CompareTo(other.Kilograms);

    public bool Equals(Mass other) =>
        Kilograms.Equals(other.Kilograms);

    public bool Equals(Mass other, double epsilon) =>
        Math.Abs(other.Kilograms - Kilograms) < epsilon;

    public override bool Equals(object?  obj) =>
        obj is Mass m && Equals(m);

    public override int GetHashCode() =>
        Kilograms.GetHashCode();

    public Mass Add(Mass rhs) =>
        new (Kilograms + rhs.Kilograms);

View on GitHub (pinned to 2f0e362824)