JamesNK/Newtonsoft.Json · error · InvalidOperationException
Cannot change {0} during a collection change event.
Error message
Cannot change {0} during a collection change event. What it means
CheckReentrancy throws InvalidOperationException when you try to mutate a JContainer (Add/Insert/Remove/SetItem/Clear) from within a CollectionChanged or ListChanged handler raised by that same container. The internal _busy flag guards against reentrant edits that would corrupt the token linked-list (Previous/Next/Parent).
Source
Thrown at Src/Newtonsoft.Json/Linq/JContainer.cs:134
if (copyAnnotations)
{
CopyAnnotations(this, other);
}
int i = 0;
foreach (JToken child in other)
{
TryAddInternal(i, child, false, copyAnnotations);
i++;
}
}
internal void CheckReentrancy()
{
#if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED)
if (_busy)
{
throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType()));
}
#endif
}
internal virtual IList<JToken> CreateChildrenCollection()
{
return new List<JToken>();
}
#if HAVE_COMPONENT_MODEL
/// <summary>
/// Raises the <see cref="AddingNew"/> event.
/// </summary>
/// <param name="e">The <see cref="AddingNewEventArgs"/> instance containing the event data.</param>
protected virtual void OnAddingNew(AddingNewEventArgs e)
{
_addingNew?.Invoke(this, e);
}View on GitHub (pinned to 4f73e74372)
Solutions
- Do not mutate the raising collection inside its own handler; defer the change to after the event completes.
- Queue the desired mutation and apply it from outside the handler (e.g. via a dispatcher or a separate pass).
- Operate on a different JContainer instance, or detach the handler before mutating.
Example fix
// before container.CollectionChanged += (s, e) => container.Add(extra); // after container.CollectionChanged += (s, e) => pendingAdds.Add(extra); // apply pendingAdds to container after the handler returns
Defensive patterns
Strategy: validation
Validate before calling
// never mutate the raising container in its own handler.
container.CollectionChanged += (s, e) => {
// queue work instead of mutating 'container' here
_deferred.Enqueue(() => container.Add(extra));
}; Try / catch
try { container.Add(item); }
catch (InvalidOperationException ex) when (ex.Message.Contains("during a collection change event")) {
// defer the mutation outside the event handler
} Prevention
- Never call Add/Insert/Remove/Replace/Clear on the sender inside its CollectionChanged handler.
- Queue mutations and flush them after the handler returns via a dispatcher/Task.
- Detach the handler or mutate a different instance when synchronizing bindings.
When it happens
Trigger: Subscribing to CollectionChanged (or ListChanged) and calling Add/Remove/Replace/Insert/Clear on the sender inside the handler.
Common situations: WPF/WinForms data-binding sync code that mutates the bound collection in a change callback; reactive code that re-enters the collection.
Related errors
- Cannot change schema while validating JSON.
- The JsonReader should not be on a token of type {0}.
- Index must be within the bounds of the List.
- Index is less than 0.
- Index is equal to or greater than Count.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/cc004bac2487333e.
Report an issue: GitHub.