JamesNK/Newtonsoft.Json · error · JsonException

New item to be added to collection must be compatible with {

Error message

New item to be added to collection must be compatible with {0}.

What it means

Thrown by IBindingList.AddNew on a JContainer when the AddingNew handler did supply an object but it is not a JToken. AddNew validates that the user-provided NewObject is assignable to JToken; otherwise it throws JsonException because a JContainer can only hold JToken children.

Source

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

        #region IBindingList Members
#if HAVE_COMPONENT_MODEL
        void IBindingList.AddIndex(PropertyDescriptor property)
        {
        }

        object IBindingList.AddNew()
        {
            AddingNewEventArgs args = new AddingNewEventArgs();
            OnAddingNew(args);

            if (args.NewObject == null)
            {
                throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType()));
            }

            if (!(args.NewObject is JToken newItem))
            {
                throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken)));
            }

            Add(newItem);

            return newItem;
        }

        bool IBindingList.AllowEdit => true;

        bool IBindingList.AllowNew => true;

        bool IBindingList.AllowRemove => true;

        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
            throw new NotSupportedException();
        }

View on GitHub (pinned to 4f73e74372)

Solutions

  1. In the AddingNew handler, wrap or build a JToken: e.NewObject = JToken.FromObject(myPoco) or new JObject(new JProperty("x", val)).
  2. Return a fresh empty JObject/JArray/JValue matching the container's expected child type.
  3. Avoid AddNew; construct the JToken yourself and call Add.

Example fix

// before
jArray.AddingNew += (s, e) => e.NewObject = new MyItem(); // not a JToken

// after
jArray.AddingNew += (s, e) => e.NewObject = JToken.FromObject(new MyItem());
Defensive patterns

Strategy: type-guard

Validate before calling

static JToken ToJToken(object o) => o switch
{
    JToken t => t,
    _ => JToken.FromObject(o)
};

jArray.AddingNew += (s, e) => e.NewObject = ToJToken(CreateNewItem());

Type guard

static bool IsJTokenCompatible(object? o) => o is JToken;

Try / catch

try { ((IBindingList)container).AddNew(); }
catch (JsonException ex) when (ex.Message.Contains("must be compatible with"))
{
    // Handler returned a non-JToken; wrap and add manually.
    container.Add(JToken.FromObject(CreateNewItem()));
}

Prevention

When it happens

Trigger: Subscribing to AddingNew and setting e.NewObject to a POCO, string, int, DataRow, or any non-JToken type, then triggering AddNew (directly or via BindingSource.AddNew).

Common situations: Handlers that return a domain model instead of a JSON node; copy-paste of an AddingNew handler from a non-JToken list; mixing typed model objects into a JObject/JArray binding surface.

Related errors


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