{"record":{"id":"3f374c863defd7f7","repo":"JamesNK/Newtonsoft.Json","slug":"argument-is-not-a-jtoken","errorCode":null,"errorMessage":"Argument is not a JToken.","messagePattern":"Argument is not a JToken\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Linq/JContainer.cs","lineNumber":1040,"sourceCode":"        bool ICollection<JToken>.Remove(JToken item)\n        {\n            return RemoveItem(item);\n        }\n        #endregion\n\n        private JToken? EnsureValue(object? value)\n        {\n            if (value == null)\n            {\n                return null;\n            }\n\n            if (value is JToken token)\n            {\n                return token;\n            }\n\n            throw new ArgumentException(\"Argument is not a JToken.\");\n        }\n\n        #region IList Members\n        int IList.Add(object? value)\n        {\n            Add(EnsureValue(value));\n            return Count - 1;\n        }\n\n        void IList.Clear()\n        {\n            ClearItems();\n        }\n\n        bool IList.Contains(object? value)\n        {\n            return ContainsItem(EnsureValue(value));\n        }","sourceCodeStart":1022,"sourceCodeEnd":1058,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Linq/JContainer.cs#L1022-L1058","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n((IList)jArray).Add(\"hello\"); // ArgumentException: not a JToken\n\n// after\njArray.Add(new JValue(\"hello\"));\n// or use the generic surface\n((IList<JToken>)jArray).Add(new JValue(\"hello\"));","handlingStrategy":"type-guard","validationCode":"static JToken? SafeValue(object? v) => v switch\n{\n    null => null,\n    JToken t => t,\n    _ => JToken.FromObject(v)\n};","typeGuard":"static bool IsJTokenOrNull(object? v) => v is null or JToken;","tryCatchPattern":"try { ((IList)container).Add(item); }\ncatch (ArgumentException ex) when (ex.Message == \"Argument is not a JToken.\")\n{\n    ((IList<JToken>)container).Add(JToken.FromObject(item));\n}","preventionTips":["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."],"tags":["newtonsoft-json","linq-to-json","ilist","type-mismatch"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}