OrchardCMS/OrchardCore · error · InvalidCastException

Cannot convert to Char

Error message

Cannot convert {value} to Char

What it means

The explicit (char) cast operator on JsonDynamicValue calls GetValue<char>() and throws InvalidCastException when the value is null or not a single-character JSON value. JSON has no char token, so only strings/numbers that Newtonsoft can narrow to char succeed.

Solutions

  1. Use the explicit char? cast or GetValue<char?>() and treat null explicitly.
  2. Convert via string: var s = value?.ToString(); if (s?.Length == 1) ch = s[0];
  3. Validate the token is a length-1 string before casting.
  4. Catch InvalidCastException when the shape of dynamic data is uncertain.

Example fix

// before
char code = (char)field.Value; // throws for "AB"
// after
var s = field.Value?.ToString();
char code = s?.Length == 1 ? s[0] : '\0';
Defensive patterns

Strategy: type-guard

Validate before calling

bool IsSingleChar(JsonDynamicValue v) => v?.ToString() is { Length: 1 };

Type guard

static bool TryGetChar(JsonDynamicValue v, out char value)
{
    var s = v?.ToString();
    if (s?.Length == 1) { value = s[0]; return true; }
    value = default; return false;
}

Try / catch

char code;
try { code = (char)field.Value; }
catch (InvalidCastException) { var s = field.Value?.ToString(); code = s?.Length == 1 ? s[0] : '\0'; }

Prevention

When it happens

Trigger: Casting (char)someJsonDynamicValue where the token is an empty string, a multi-character string like "ab", a non-numeric value, or null.

Common situations: Single-letter codes stored as JSON strings that occasionally arrive empty or longer; deserialized data where a char field was serialized as string and later widened.

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

Appendix: source

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

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

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

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

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

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

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

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

View on GitHub (pinned to 4306c0717f)