JamesNK/Newtonsoft.Json · error · ArgumentException

Argument is not a JToken.

Error message

Argument is not a JToken.

What it means

Thrown by JContainer.EnsureValue when an object passed to the non-generic IList members (Add, Insert, Contains, IndexOf, Remove, the object indexer setter) is non-null but is not a JToken. JContainer's non-generic IList accepts only null or JToken instances; any other CLR type is rejected with ArgumentException.

Source

Thrown at Src/Newtonsoft.Json/Linq/JContainer.cs:1040

        bool ICollection<JToken>.Remove(JToken item)
        {
            return RemoveItem(item);
        }
        #endregion

        private JToken? EnsureValue(object? value)
        {
            if (value == null)
            {
                return null;
            }

            if (value is JToken token)
            {
                return token;
            }

            throw new ArgumentException("Argument is not a JToken.");
        }

        #region IList Members
        int IList.Add(object? value)
        {
            Add(EnsureValue(value));
            return Count - 1;
        }

        void IList.Clear()
        {
            ClearItems();
        }

        bool IList.Contains(object? value)
        {
            return ContainsItem(EnsureValue(value));
        }

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Wrap the value in a JToken before insertion: use new JValue(value), JToken.FromObject(value), or new JObject(...)/new JArray(...).
  2. Use the generic IList<JToken> / public Add(object) overload which auto-wraps, instead of the non-generic IList cast.
  3. Add a type check (value is JToken) before calling the non-generic IList members.

Example fix

// before
((IList)jArray).Add("hello"); // ArgumentException: not a JToken

// after
jArray.Add(new JValue("hello"));
// or use the generic surface
((IList<JToken>)jArray).Add(new JValue("hello"));
Defensive patterns

Strategy: type-guard

Validate before calling

static JToken? SafeValue(object? v) => v switch
{
    null => null,
    JToken t => t,
    _ => JToken.FromObject(v)
};

Type guard

static bool IsJTokenOrNull(object? v) => v is null or JToken;

Try / catch

try { ((IList)container).Add(item); }
catch (ArgumentException ex) when (ex.Message == "Argument is not a JToken.")
{
    ((IList<JToken>)container).Add(JToken.FromObject(item));
}

Prevention

When it happens

Trigger: Calling the non-generic IList API on a JObject/JArray with a raw CLR value, e.g. ((IList)myArray).Add("literal"), ((IList)myArray)[0] = 42, or passing an int/string/POCO to IList.Add/Insert/Contains/IndexOf/Remove. Often happens when interacting with JContainer through System.Collections.IList or reflection.

Common situations: Reflection/dynamic code that treats the container as a plain IList and pushes primitives; copy loops that assume IList accepts any object; generic helpers that box values before inserting.

Related errors


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