JamesNK/Newtonsoft.Json · error · ArgumentException
Object must be of type TimeSpan.
Error message
Object must be of type TimeSpan.
What it means
Thrown by JValue.CompareTo when the token's JSON type is JTokenType.TimeSpan and the operand is not a TimeSpan. TimeSpan JValues are compared with TimeSpan.CompareTo; a non-TimeSpan operand is rejected. This is the last of the four type-strict primitive comparisons (Bytes/Guid/Uri/TimeSpan) inside CompareTo.
Source
Thrown at Src/Newtonsoft.Json/Linq/JValue.cs:394
Guid guid1 = (Guid)objA;
Guid guid2 = (Guid)objB;
return guid1.CompareTo(guid2);
case JTokenType.Uri:
Uri? uri2 = objB as Uri;
if (uri2 == null)
{
throw new ArgumentException("Object must be of type Uri.");
}
Uri uri1 = (Uri)objA;
return Comparer<string>.Default.Compare(uri1.ToString(), uri2.ToString());
case JTokenType.TimeSpan:
if (!(objB is TimeSpan))
{
throw new ArgumentException("Object must be of type TimeSpan.");
}
TimeSpan ts1 = (TimeSpan)objA;
TimeSpan ts2 = (TimeSpan)objB;
return ts1.CompareTo(ts2);
default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(valueType), valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType));
}
}
private static int CompareFloat(object objA, object objB)
{
double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture);
double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture);
// take into account possible floating point errors
if (MathUtils.ApproxEquals(d1, d2))View on GitHub (pinned to 4f73e74372)
Solutions
- Parse the operand to TimeSpan before comparing: token.CompareTo(TimeSpan.Parse(text)).
- Compare the underlying values: token.Value<TimeSpan>() vs TimeSpan.FromSeconds(n).
- Type-check the operand before invoking CompareTo.
Example fix
// before
int c = tsToken.CompareTo("00:05:00");
// after
int c = tsToken.CompareTo(TimeSpan.Parse("00:05:00")); Defensive patterns
Strategy: type-guard
Validate before calling
if (other is TimeSpan ts) { int c = token.CompareTo(ts); } else if (other is string s) { int c = token.CompareTo(TimeSpan.Parse(s)); } Type guard
static bool IsTimeSpan(object? o) => o is TimeSpan;
Try / catch
try { int c = token.CompareTo(other); } catch (ArgumentException ex) when (ex.Message.Contains("TimeSpan")) { /* parse string to TimeSpan */ } Prevention
- Parse duration strings to TimeSpan before comparing.
- Standardize on TimeSpan for duration fields.
- Type-check operands in heterogeneous comparisons.
When it happens
Trigger: Comparing a TimeSpan JValue against a string such as token.CompareTo("00:01:00") or an integer number of ticks. Triggered during sorting/equality on token collections that contain duration fields.
Common situations: Duration/delay fields deserialized as TimeSpan then compared to string or numeric literals; mixing TimeSpan and string duration representations.
Related errors
- Object must be of type byte[].
- Object must be of type Guid.
- Object must be of type Uri.
- Could not determine JSON object type for type {0}.
- Cannot access child value on {0}.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/3a2b1e159a38d88a.
Report an issue: GitHub.