OrchardCMS/OrchardCore · error · InvalidCastException

Cannot convert to Int16

Error message

Cannot convert {value} to Int16

What it means

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

Solutions

  1. Cast to short? (explicit operator short?) instead of short, which returns null instead of throwing, then handle the null case.
  2. Validate the JSON value with TryGetValue/GetValue and check the numeric type and range before casting.
  3. Ensure the JSON field is stored as a JSON number within Int16 range; fix the producing side or the schema if it is a string.
  4. Wrap the cast in try/catch for InvalidCastException if the value is genuinely optional.

Example fix

// before
short port = (short)jsonValue; // throws when jsonValue is "8080" (string) or 70000

// after
short? port = (short?)jsonValue;
if (port 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 Int16 cast.");
if (jsonValue.Value<long>() is < short.MinValue or > short.MaxValue)
    throw new InvalidOperationException($"Value {jsonValue} is outside Int16 range.");

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Casting a JsonDynamicValue instance to short with (short)jsonDynamicValue when the wrapped JSON token is null, not a number, or a number outside the Int16 range (-32768..32767), causing GetValue<short>() to yield null.

Common situations: Reading JSON payloads where a field is a string like "42" instead of a number, casting large numbers (e.g. 70000) to short, casting on a JsonDynamicValue that was constructed from a null/default _jsonValue, or schema changes in serialized data altering a field's type.

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

Appendix: source

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

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

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

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

View on GitHub (pinned to 4306c0717f)