OrchardCMS/OrchardCore · error · InvalidCastException

Cannot convert to Boolean

Error message

Cannot convert {value} to Boolean

What it means

The explicit (bool) cast operator on JsonDynamicValue calls GetValue<bool>() on the underlying JValue and throws InvalidCastException when the value is null or not a JSON boolean. Dynamic JSON values only support the cast when the token is actually a boolean — no truthiness coercion is performed.

Solutions

  1. Use the explicit bool? cast or GetValue<bool?>() and treat null as false instead of the throwing non-nullable cast.
  2. If the token is a string, parse it: bool.TryParse(value.ToString(), out var b).
  3. Verify the JSON token type before casting (value?._jsonValue?.Type == JTokenType.Boolean).
  4. Catch InvalidCastException if the shape of the data is uncertain.

Example fix

// before
bool enabled = (bool)part.Value; // throws for "true" string
// after
var raw = part.Value?._jsonValue?.ToString();
bool enabled = bool.TryParse(raw, out var b) && b;
Defensive patterns

Strategy: type-guard

Validate before calling

bool IsJsonBoolean(JsonDynamicValue v) =>
    v?._jsonValue?.Type == JTokenType.Boolean;

Type guard

static bool TryGetBool(JsonDynamicValue v, out bool value)
{
    if (v?._jsonValue?.Type == JTokenType.Boolean) { value = v._jsonValue.Value<bool>(); return true; }
    if (bool.TryParse(v?.ToString(), out var b)) { value = b; return true; }
    value = default; return false;
}

Try / catch

bool enabled;
try { enabled = (bool)part.Value; }
catch (InvalidCastException) { enabled = bool.TryParse(part.Value?.ToString(), out var b) && b; }

Prevention

When it happens

Trigger: Writing (bool)someJsonDynamicValue where the value is a string "true", a number 1, null, or any non-boolean token.

Common situations: Treating JSON string flags like "true"/"false" as booleans; content fields whose type changed from boolean to text; conditional checks on possibly-null dynamic properties.

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

Appendix: source

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

        }

        return left.Equals(right);
    }

    public static bool operator !=(JsonDynamicValue left, JsonDynamicValue right) => !(left == right);

    public static bool operator <(JsonDynamicValue left, JsonDynamicValue right) => ReferenceEquals(left, null) ? !ReferenceEquals(right, null) : left.CompareTo(right) < 0;

    public static bool operator <=(JsonDynamicValue left, JsonDynamicValue right) => ReferenceEquals(left, null) || left.CompareTo(right) <= 0;

    public static bool operator >(JsonDynamicValue left, JsonDynamicValue right) => !ReferenceEquals(left, null) && left.CompareTo(right) > 0;

    public static bool operator >=(JsonDynamicValue left, JsonDynamicValue right) => ReferenceEquals(left, null) ? ReferenceEquals(right, null) : left.CompareTo(right) >= 0;

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

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

View on GitHub (pinned to 4306c0717f)