OrchardCMS/OrchardCore · error · InvalidCastException
Cannot convert to TimeSpan
Error message
Cannot convert {value} to TimeSpan What it means
This InvalidCastException is thrown by the explicit TimeSpan conversion operator on JsonDynamicValue when the wrapped JSON value is not a string, since TimeSpan is parsed from its string representation using TimeSpan.Parse with invariant culture. Non-string JSON values (numbers, objects, null) cannot be converted.
Solutions
- Ensure the JSON field is a string in TimeSpan.Parse format (e.g. 'hh:mm:ss' or 'd.hh:mm:ss')
- Get the string first and parse with TimeSpan.TryParse yourself
- Validate with GetObjectValue() is string before casting
- Convert numeric durations (e.g. seconds) manually before casting
Example fix
// before
var ts = (TimeSpan)dynamicValue;
// after
if (dynamicValue?.GetObjectValue() is string s && TimeSpan.TryParse(s, CultureInfo.InvariantCulture, out var ts))
{
// use ts
} Defensive patterns
Strategy: type-guard
Validate before calling
if (value?.GetObjectValue() is not string ts || !TimeSpan.TryParse(ts, CultureInfo.InvariantCulture, out _))
throw new InvalidOperationException("JSON value is not a parseable TimeSpan string"); Type guard
static bool IsTimeSpanString(JsonDynamicValue? v) =>
v?.GetObjectValue() is string s && TimeSpan.TryParse(s, CultureInfo.InvariantCulture, out _); Try / catch
TimeSpan ts;
try { ts = (TimeSpan)dynamicValue; }
catch (InvalidCastException ex) { /* log, fallback */ ts = TimeSpan.Zero; } Prevention
- Store durations as invariant-culture TimeSpan strings in JSON
- Convert numeric durations (seconds/milliseconds) to TimeSpan manually before casting
- Use TimeSpan.TryParse on your side instead of the throwing cast
- Handle JSON null explicitly
When it happens
Trigger: Casting a JsonDynamicValue with (TimeSpan) when the wrapped value is a number, object, array, or null instead of a duration string like '1.02:03:04'.
Common situations: Durations serialized as milliseconds/seconds by APIs; null fields; strings not in an invariant-culture parseable TimeSpan format will fail inside TimeSpan.Parse.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Cannot convert to Int16
- Cannot convert to Int32
- Cannot convert to Int64
- Cannot convert to SByte
- Cannot convert to Float
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/1939851c447e1eb8.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Abstractions/Json/Dynamic/JsonDynamicValue.cs:469
public static explicit operator byte[]?(JsonDynamicValue value)
{
if (value?._jsonValue.GetObjectValue() is string str)
{
return Convert.FromBase64String(str);
}
throw new InvalidCastException($"Cannot convert {value} to Byte array");
}
public static explicit operator TimeSpan(JsonDynamicValue value)
{
if (value?._jsonValue?.GetObjectValue() is string str)
{
return TimeSpan.Parse(str, CultureInfo.InvariantCulture);
}
throw new InvalidCastException($"Cannot convert {value} to TimeSpan");
}
public static explicit operator TimeSpan?(JsonDynamicValue value)
{
var str = value?._jsonValue?.GetObjectValue() as string;
return str is not null
? TimeSpan.Parse(str, CultureInfo.InvariantCulture)
: null;
}
public static explicit operator Uri?(JsonDynamicValue value)
{
return new(value?._jsonValue?.GetValue<string>() ?? string.Empty);
}
public static implicit operator JsonDynamicValue(bool value)
{View on GitHub (pinned to 4306c0717f)