JamesNK/Newtonsoft.Json · error · InvalidCastException
Cannot cast {0} to {1}.
Error message
Cannot cast {0} to {1}. What it means
Thrown by the internal Convert<T,U>(T token) when the token is not directly castable to U and is not a JValue. The conversion path supports (a) tokens that are already assignable to U, and (b) JValue tokens whose underlying .Value is converted via Convert.ChangeType. Any other token type (e.g. JObject, JArray, JProperty when U is a primitive) cannot be converted and raises InvalidCastException naming the token's runtime type and the target type T.
Source
Thrown at Src/Newtonsoft.Json/Linq/Extensions.cs:275
{
if (token == null)
{
#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter.
return default;
#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter.
}
if (token is U castValue
// don't want to cast JValue to its interfaces, want to get the internal value
&& typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable))
{
return castValue;
}
else
{
if (!(token is JValue value))
{
throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T)));
}
if (value.Value is U u)
{
return u;
}
Type targetType = typeof(U);
if (ReflectionUtils.IsNullableType(targetType))
{
if (value.Value == null)
{
#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter.
return default;
#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter.
}
View on GitHub (pinned to 4f73e74372)
Solutions
- Navigate to the leaf JValue before converting (e.g. obj["foo"]["bar"].Value<int>() selecting a scalar, not obj["foo"]).
- Check token.Type == JTokenType.Integer/String/etc. (or token is JValue) before calling Value<T,U>.
- Use SelectToken with a more precise JSONPath that resolves to a scalar leaf.
Example fix
// before int n = obj.Value<int>(); // obj is JObject, not JValue // after int n = obj["count"].Value<int>();
Defensive patterns
Strategy: type-guard
Validate before calling
if (token is JValue jv)
{
int n = jv.Value<int>();
} Type guard
static bool IsLeafValue(JToken t) => t is JValue; static bool CanConvertTo<T>(JToken t) => t is JValue or T;
Prevention
- Navigate to the leaf JValue before scalar conversion.
- Check token is JValue (or token.Type matches) before Value<T>.
- Use precise JSONPath in SelectToken to target scalar leaves.
When it happens
Trigger: Calling .Value<int>() / .Value<string>() on a JToken that is a JObject/JArray/JProperty (not a JValue); converting a container token to a scalar; mismatched generic type arguments in Value<T,U>.
Common situations: Assuming a JToken selected via SelectToken is a scalar when it is actually an object/array; converting LINQ query results whose nodes are containers; off-by-one in a JSONPath selecting a parent instead of a leaf.
Related errors
- Source value must be a JToken.
- Argument is not a JToken.
- New item to be added to collection must be compatible with {
- Can not add {0} to {1}.
- Accessed JObject values with invalid key value: {0}. Object
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/049d8f65388f2703.
Report an issue: GitHub.