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

  1. Ensure the JSON field is a string in TimeSpan.Parse format (e.g. 'hh:mm:ss' or 'd.hh:mm:ss')
  2. Get the string first and parse with TimeSpan.TryParse yourself
  3. Validate with GetObjectValue() is string before casting
  4. 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

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


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)