OrchardCMS/OrchardCore · error · InvalidCastException

Cannot convert to Int32

Error message

Cannot convert {value} to Int32

What it means

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

Solutions

  1. Cast to int? (explicit operator int?) instead of int, 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 within Int32 range before casting.
  3. Ensure the JSON field is stored as a JSON number; fix the producer or deserialize the string via int.Parse when it is intentionally a string.
  4. Wrap the cast in try/catch for InvalidCastException if the value is genuinely optional.

Example fix

// before
int count = (int)jsonValue; // throws when jsonValue is "123" (string)

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

Strategy: type-guard

Validate before calling

if (jsonValue is null || jsonValue.Type != JTokenType.Integer)
    throw new InvalidOperationException("Expected an integer JSON value for Int32 cast.");

Type guard

static bool IsConvertibleToInt32(JsonDynamicValue v) =>
    v?._jsonValue is { Type: JTokenType.Integer } t && t.Value<long>() is >= int.MinValue and <= int.MaxValue;

Try / catch

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

Prevention

When it happens

Trigger: Casting a JsonDynamicValue instance to int with (int)jsonDynamicValue when the wrapped JSON token is null, not a number (e.g. a JSON string or object), or a number outside the Int32 range, causing GetValue<int>() to yield null.

Common situations: Reading a JSON id or count field that is a string ("123"), casting a fractional or very large number that Json.NET's GetValue<int> rejects, casting on a JsonDynamicValue built from a null token, or upstream data changing from number to string.

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/ca5dce6106af89f3. Report an issue: GitHub.

Appendix: source

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

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

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

    public static explicit operator short?(JsonDynamicValue value)
    {
        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?>();
    }

View on GitHub (pinned to 4306c0717f)