OrchardCMS/OrchardCore · error · InvalidCastException

Cannot convert to Int64

Error message

Cannot convert {value} to Int64

What it means

JsonDynamicValue wraps a JSON value and exposes explicit conversion operators for primitive types. The explicit operator long casts _jsonValue.GetValue<long>(); if the underlying JSON value is absent, null, or not representable as an Int64, the operator returns null and throws InvalidCastException with 'Cannot convert {value} to Int64'. It signals that the requested numeric conversion is not possible for the wrapped JSON token.

Solutions

  1. Cast to long? (explicit operator long?) instead of long, which returns null instead of throwing, then handle the null case.
  2. Validate the JSON value with TryGetValue/GetValue and confirm it is an integral number before casting.
  3. Ensure the JSON field is a JSON number; if it is a string, parse it explicitly (long.TryParse) instead of casting.
  4. Wrap the cast in try/catch for InvalidCastException if the value is genuinely optional.

Example fix

// before
long id = (long)jsonValue; // throws when jsonValue is 3.14 or "9007199254740993"

// after
long? id = (long?)jsonValue;
if (id is null) { /* handle missing/invalid value */ }
Defensive patterns

Strategy: type-guard

Validate before calling

if (jsonValue is null || (jsonValue.Type != JTokenType.Integer && jsonValue.Type != JTokenType.Float))
    throw new InvalidOperationException("Expected a numeric JSON value for Int64 cast.");

Type guard

static bool IsConvertibleToInt64(JsonDynamicValue v) =>
    v?._jsonValue is { Type: JTokenType.Integer };

Try / catch

try
{
    long n = (long)jsonValue;
}
catch (InvalidCastException ex)
{
    // log and fall back to a default or skip the record
    long n = default;
}

Prevention

When it happens

Trigger: Casting a JsonDynamicValue instance to long with (long)jsonDynamicValue when the wrapped JSON token is null, not a number, or a non-integral/overflowing number (e.g. 3.14 or a value beyond Int64), causing GetValue<long>() to yield null.

Common situations: Reading timestamps or large ids stored as fractional numbers or numeric strings, casting on a JsonDynamicValue constructed from a null/default _jsonValue, or JSON produced by another language serializing longs as strings.

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 OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/b4d7db4cf6c268c9. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.Abstractions/Json/Dynamic/JsonDynamicValue.cs:384

    {
        return value?._jsonValue?.GetValue<short?>();
    }

    public static explicit operator int(JsonDynamicValue value)
    {
        return value?._jsonValue?.GetValue<int>()
            ?? throw new InvalidCastException($"Cannot convert {value} to Int32");
    }

    public static explicit operator int?(JsonDynamicValue value)
    {
        return value?._jsonValue?.GetValue<int?>();
    }

    public static explicit operator long(JsonDynamicValue value)
    {
        return value?._jsonValue?.GetValue<long>()
            ?? throw new InvalidCastException($"Cannot convert {value} to Int64");
    }

    public static explicit operator long?(JsonDynamicValue value)
    {
        return value?._jsonValue?.GetValue<long?>();
    }

    public static explicit operator sbyte(JsonDynamicValue value)
    {
        return value?._jsonValue?.GetValue<sbyte>()
            ?? throw new InvalidCastException($"Cannot convert {value} to SByte");
    }

    public static explicit operator sbyte?(JsonDynamicValue value)
    {
        return value?._jsonValue?.GetValue<sbyte?>();
    }

View on GitHub (pinned to 4306c0717f)