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
- Wrap the value in a JToken before insertion: use new JValue(value), JToken.FromObject(value), or new JObject(...)/new JArray(...).
- Use the generic IList<JToken> / public Add(object) overload which auto-wraps, instead of the non-generic IList cast.
- 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
- Prefer the generic IList<JToken> and public Add(object) overloads which auto-wrap values.
- Never cast to the non-generic System.Collections.IList when inserting user values.
- Wrap non-JToken inputs with JToken.FromObject or new JValue before insertion.
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
- 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
- Set JObject values with invalid key value: {0}. Object prope
- Object serialized to {0}. JObject instance expected.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/3f374c863defd7f7.
Report an issue: GitHub.