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
- Use the explicit bool? cast or GetValue<bool?>() and treat null as false instead of the throwing non-nullable cast.
- If the token is a string, parse it: bool.TryParse(value.ToString(), out var b).
- Verify the JSON token type before casting (value?._jsonValue?.Type == JTokenType.Boolean).
- 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
- Never cast dynamic JSON values to non-nullable primitives without checking the token type first.
- Prefer the bool? cast so null/absent values flow through instead of throwing.
- For string flags ("true"/"1"), parse with bool.TryParse instead of casting.
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
- Cannot convert to Byte
- Cannot convert to Char
- Cannot convert to
- Cannot convert to UInt32
- Cannot convert to UInt64
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)