OrchardCMS/OrchardCore · error · InvalidOperationException
Cannot convert to
Error message
Cannot convert {this} to {conversionType} What it means
JsonDynamicValue implements IConvertible; when ToType is called the underlying JValue is converted with ToObject(conversionType). If the JSON value cannot be converted to the requested type (or the value is null), an InvalidOperationException with 'Cannot convert ...' is thrown.
Solutions
- Check the underlying JSON token type (JsonValue.Type) before converting and branch on it.
- Use ToString(provider) plus type-specific parsing (int.TryParse, DateTime.Parse with culture) for resilient conversion.
- Handle null dynamic values explicitly before invoking conversion.
- Catch InvalidOperationException and fall back to a default value appropriate for the field.
Example fix
// before var count = (int)Convert.ChangeType(jsonValue, typeof(int)); // after var raw = jsonValue?.ToString(); var count = int.TryParse(raw, NumberStyles.Any, CultureInfo.InvariantCulture, out var c) ? c : 0;
Defensive patterns
Strategy: type-guard
Validate before calling
// Confirm the underlying token supports the target conversion
bool CanConvertTo(JsonDynamicValue v, Type t) =>
v?._jsonValue != null &&
!(t.IsPrimitive && (v._jsonValue.Type == JTokenType.Object || v._jsonValue.Type == JTokenType.Array)); Type guard
static bool IsConvertible<T>(JsonDynamicValue v, out T result)
{
try { result = (T)Convert.ChangeType(v?.ToString(), typeof(T), CultureInfo.InvariantCulture); return true; }
catch { result = default; return false; }
} Try / catch
try
{
var converted = Convert.ChangeType(jsonValue, conversionType, CultureInfo.InvariantCulture);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Cannot convert"))
{
// fall back to string parsing or a default value
} Prevention
- Prefer ToString + TryParse over IConvertible.ToType for dynamic JSON.
- Check the JValue token type before converting primitives.
- Handle null dynamic values explicitly before conversion.
When it happens
Trigger: Calling Convert.ChangeType(dynamicJsonValue, someType) or another IConvertible.ToType path where the JValue's runtime JSON type is incompatible with conversionType — e.g. converting a JSON string "abc" to int, an object/array to a primitive, or a null value to any type.
Common situations: Dynamic content-field values whose shape changed between data versions; recipes importing strings that were assumed numeric; querying dynamic documents and casting values with Convert.ChangeType.
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 Boolean
- Cannot convert to Byte
- Cannot convert to Char
- Cannot convert to UInt32
- Cannot convert to UInt64
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/4f2a11b94efc7cf1.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Abstractions/Json/Dynamic/JsonDynamicValue.cs:233
sbyte IConvertible.ToSByte(IFormatProvider? provider)
{
return (sbyte)this;
}
float IConvertible.ToSingle(IFormatProvider? provider)
{
return (float)this;
}
string IConvertible.ToString(IFormatProvider? provider)
{
return ToString(provider);
}
object IConvertible.ToType(Type conversionType, IFormatProvider? provider)
{
return _jsonValue?.ToObject(conversionType)
?? throw new InvalidOperationException($"Cannot convert {this} to {conversionType}");
}
ushort IConvertible.ToUInt16(IFormatProvider? provider)
{
return (ushort)this;
}
uint IConvertible.ToUInt32(IFormatProvider? provider)
{
return (uint)this;
}
ulong IConvertible.ToUInt64(IFormatProvider? provider)
{
return (ulong)this;
}
public static bool operator ==(JsonDynamicValue left, JsonDynamicValue right)View on GitHub (pinned to 4306c0717f)