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

  1. Navigate to the leaf JValue before converting (e.g. obj["foo"]["bar"].Value<int>() selecting a scalar, not obj["foo"]).
  2. Check token.Type == JTokenType.Integer/String/etc. (or token is JValue) before calling Value<T,U>.
  3. 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

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


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/049d8f65388f2703. Report an issue: GitHub.