JamesNK/Newtonsoft.Json · error · ArgumentException

Value is not a JToken.

Error message

Value is not a JToken.

What it means

Thrown by JsonFormatterConverter.Convert(object, Type) when the value handed to the IFormatterConverter is not a JToken. JsonFormatterConverter is the bridge used while deserializing ISerializable types (types implementing ISerializable with a serialization constructor); each value passed to the ISerializable constructor is expected to be a JToken parsed from the JSON stream.

Source

Thrown at Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs:69

            _contract = contract;
            _member = member;
        }

        private T GetTokenValue<T>(object value)
        {
            ValidationUtils.ArgumentNotNull(value, nameof(value));

            JValue v = (JValue)value;
            return (T)System.Convert.ChangeType(v.Value, typeof(T), CultureInfo.InvariantCulture)!;
        }

        public object Convert(object value, Type type)
        {
            ValidationUtils.ArgumentNotNull(value, nameof(value));

            if (!(value is JToken token))
            {
                throw new ArgumentException("Value is not a JToken.", nameof(value));
            }

            return _reader.CreateISerializableItem(token, type, _contract, _member)!;
        }

        public object Convert(object value, TypeCode typeCode)
        {
            ValidationUtils.ArgumentNotNull(value, nameof(value));

            object? resolvedValue = (value is JValue v) ? v.Value : value;

            return System.Convert.ChangeType(resolvedValue, typeCode, CultureInfo.InvariantCulture)!;
        }

        public bool ToBoolean(object value)
        {
            return GetTokenValue<bool>(value);
        }

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Avoid implementing ISerializable for types you serialize as JSON; prefer plain POCOs with [JsonObject]/[JsonProperty].
  2. If ISerializable is required, ensure the serialization stream contains native JSON values that become JTokens.
  3. Remove or adjust any custom JsonConverter that reads ISerializable types and injects non-JToken values.
  4. Report a repro if reached through pure library code without custom converters.

Example fix

// before: ISerializable type with custom converter injecting non-JToken
[JsonConverter(typeof(MyBadConverter))]
[Serializable] public class Foo : ISerializable { ... }
// after: drop ISerializable, use POCO
public class Foo { public int Id { get; set; } public string Name { get; set; } }
Defensive patterns

Strategy: validation

Validate before calling

if (!(value is Newtonsoft.Json.Linq.JToken)) throw new ArgumentException("expected a JToken");

Type guard

static bool IsJToken(object value) => value is Newtonsoft.Json.Linq.JToken;

Try / catch

try { JsonConvert.DeserializeObject<T>(json); }
catch (ArgumentException ex) when (ex.Message.Contains("Value is not a JToken")) {
    logger.Error(ex, "ISerializable payload contained non-JToken value; review custom converters."); throw;
}

Prevention

When it happens

Trigger: Deserializing a type that implements ISerializable and whose SerializationInfo values are not JTokens. This is an internal-protocol error, typically caused by a custom JsonConverter or ISerializable implementation that hands non-JToken objects into the converter, or by an internal pipeline mismatch during ISerializable population.

Common situations: Mixing ISerializable types with custom converters, partial deserialization via JToken.ReadFrom creating non-token inputs, edge cases with $values / typewriting during ISerializable round-tripping, version mismatches where an ISerializable contract is reused incorrectly.

Related errors


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