OrchardCMS/OrchardCore · error · InvalidCastException

Cannot convert to UInt32

Error message

Cannot convert {value} to UInt32

What it means

This InvalidCastException is thrown by the explicit ushort conversion operator on JsonDynamicValue when the wrapped JSON value is null or cannot be read as a ushort. Note the message text says 'UInt32' even though the target type is UInt16 — a copy-paste inaccuracy in the library. The cast operator uses GetValue<ushort>() which fails when the underlying JSON element is not a numeric value in ushort range.

Solutions

  1. Check the wrapped value with GetObjectValue() (type and null) before casting
  2. Cast to ushort? instead — that operator returns null instead of throwing
  3. Validate the value is a whole number within 0-65535 first
  4. Use Convert.ToUInt16 on a string representation after a null check

Example fix

// before
var n = (ushort)dynamicValue;
// after
var obj = dynamicValue?.GetObjectValue();
if (obj is JsonElement el && el.ValueKind == JsonValueKind.Number && el.TryGetUInt16(out var n)) { /* use n */ }
Defensive patterns

Strategy: type-guard

Validate before calling

if (value is null) throw new InvalidOperationException("Expected a numeric JSON value");
var obj = value.GetObjectValue();
if (obj is not JsonElement el || el.ValueKind != JsonValueKind.Number || !el.TryGetUInt16(out _))
    throw new InvalidOperationException("JSON value is not a ushort-compatible number");

Type guard

static bool IsUshortLike(JsonDynamicValue? v) =>
    v?.GetObjectValue() is JsonElement el && el.ValueKind == JsonValueKind.Number && el.TryGetUInt16(out _);

Try / catch

ushort n;
try { n = (ushort)dynamicValue; }
catch (InvalidCastException ex) { /* log ex, use fallback */ n = 0; }

Prevention

When it happens

Trigger: Casting a JsonDynamicValue with (ushort) when the wrapped JSON element is null, a string, an object/array, or a number outside 0-65535.

Common situations: Dynamic JSON data from an API where a field expected to be numeric arrives as a string or null; deserializing config-like JSON where an id/flag field is absent; iterating mixed-type JSON arrays and casting each element.

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

Appendix: source

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

    {
        return value?._jsonValue?.GetValue<float>()
            ?? throw new InvalidCastException($"Cannot convert {value} to Float");
    }

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

    public static explicit operator string?(JsonDynamicValue value)
    {
        return value?.ToString();
    }

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

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

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

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

View on GitHub (pinned to 4306c0717f)