JamesNK/Newtonsoft.Json · error · ArgumentException
Can not convert {0} to TimeSpan.
Error message
Can not convert {0} to TimeSpan. What it means
Thrown by the explicit cast operator 'operator TimeSpan(JToken)' (NON-nullable) when the token is not a TimeSpan-compatible JValue. ArgumentException {0} is the resolved JTokenType; allowed types are TimeSpanTypes ({String, Comment, Raw, TimeSpan}) — the narrowest set. Non-nullable overload, so a JSON null token ALSO throws. Only a TimeSpan or a culture-invariant TimeSpan string is accepted.
Source
Thrown at Src/Newtonsoft.Json/Linq/JToken.cs:1479
if (v.Value is byte[] bytes)
{
return new Guid(bytes);
}
return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!);
}
/// <summary>
/// Performs an explicit conversion from <see cref="JToken"/> to <see cref="TimeSpan"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator TimeSpan(JToken value)
{
JValue? v = EnsureValue(value);
if (v == null || !ValidateToken(v, TimeSpanTypes, false))
{
throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
}
return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!);
}
/// <summary>
/// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="TimeSpan"/>.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator TimeSpan?(JToken? value)
{
if (value == null)
{
return null;
}
JValue? v = EnsureValue(value);View on GitHub (pinned to 4f73e74372)
Solutions
- Use the Nullable overload (TimeSpan?)token["duration"] so JSON null returns null.
- If the value is numeric (ticks/millis), convert it yourself (TimeSpan.FromMilliseconds(...)) instead of casting.
- Guard token["duration"]?.Type is String or TimeSpan before the non-nullable cast, and use TimeSpan.TryParse.
- Normalize the producer to emit standard TimeSpan strings like "00:01:30".
Example fix
// before TimeSpan duration = (TimeSpan)payload["duration"]; // throws on integer millis // after TimeSpan duration = TimeSpan.TryParse((string?)payload["duration"], out var ts) ? ts : TimeSpan.Zero;
Defensive patterns
Strategy: validation
Validate before calling
TimeSpan duration = TimeSpan.TryParse((string?)payload["duration"], out var ts) ? ts : TimeSpan.Zero;
Type guard
static bool IsTimeSpanLike(JToken? t) =>
t is JValue v && (v.Type == JTokenType.TimeSpan || v.Type == JTokenType.String); Try / catch
TimeSpan duration;
try { duration = (TimeSpan)payload["duration"]; }
catch (ArgumentException) { duration = TimeSpan.Zero; } Prevention
- Use the Nullable overload (TimeSpan?) for fields that may be JSON null.
- Convert epoch integers via TimeSpan.FromMilliseconds/FromSeconds instead of casting.
- TimeSpanTypes is the narrowest set — only String/TimeSpan are accepted.
When it happens
Trigger: Calling (TimeSpan)token["duration"] when the JValue Type is Integer, Float, Boolean, Date, Guid, Uri, Bytes, Null, Object, or Array, or the node is a JObject/JArray (EnsureValue null). An epoch-integer duration or a number is rejected because TimeSpan parsing from numbers is ambiguous.
Common situations: Duration field emitted as an integer (ticks/millis/seconds) instead of a TimeSpan string; null duration in some records cast to non-nullable TimeSpan; field changed to an ISO duration object.
Related errors
- Can not convert {0} to Single.
- Can not convert {0} to UInt32.
- Can not convert {0} to UInt64.
- Can not convert {0} to String.
- Can not convert {0} to byte array.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/eb84f14383765711.
Report an issue: GitHub.