{"record":{"id":"cc004bac2487333e","repo":"JamesNK/Newtonsoft.Json","slug":"cannot-change-0-during-a-collection-change-event","errorCode":null,"errorMessage":"Cannot change {0} during a collection change event.","messagePattern":"Cannot change (.+?) during a collection change event\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Linq/JContainer.cs","lineNumber":134,"sourceCode":"            if (copyAnnotations)\n            {\n                CopyAnnotations(this, other);\n            }\n\n            int i = 0;\n            foreach (JToken child in other)\n            {\n                TryAddInternal(i, child, false, copyAnnotations);\n                i++;\n            }\n        }\n\n        internal void CheckReentrancy()\n        {\n#if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED)\n            if (_busy)\n            {\n                throw new InvalidOperationException(\"Cannot change {0} during a collection change event.\".FormatWith(CultureInfo.InvariantCulture, GetType()));\n            }\n#endif\n        }\n\n        internal virtual IList<JToken> CreateChildrenCollection()\n        {\n            return new List<JToken>();\n        }\n\n#if HAVE_COMPONENT_MODEL\n        /// <summary>\n        /// Raises the <see cref=\"AddingNew\"/> event.\n        /// </summary>\n        /// <param name=\"e\">The <see cref=\"AddingNewEventArgs\"/> instance containing the event data.</param>\n        protected virtual void OnAddingNew(AddingNewEventArgs e)\n        {\n            _addingNew?.Invoke(this, e);\n        }","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Linq/JContainer.cs#L116-L152","documentation":"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).","triggerScenarios":"Subscribing to CollectionChanged (or ListChanged) and calling Add/Remove/Replace/Insert/Clear on the sender inside the handler.","commonSituations":"WPF/WinForms data-binding sync code that mutates the bound collection in a change callback; reactive code that re-enters the collection.","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."],"exampleFix":"// before\ncontainer.CollectionChanged += (s, e) => container.Add(extra);\n// after\ncontainer.CollectionChanged += (s, e) => pendingAdds.Add(extra);\n// apply pendingAdds to container after the handler returns","handlingStrategy":"validation","validationCode":"// never mutate the raising container in its own handler.\ncontainer.CollectionChanged += (s, e) => {\n    // queue work instead of mutating 'container' here\n    _deferred.Enqueue(() => container.Add(extra));\n};","typeGuard":null,"tryCatchPattern":"try { container.Add(item); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"during a collection change event\")) {\n    // defer the mutation outside the event handler\n}","preventionTips":["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."],"tags":["jcontainer","reentrancy","events","invalid-operation"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}