dotnet/wpf · error · InvalidOperationException
SR.Freezable_Reentrant
Error message
SR.Freezable_Reentrant
What it means
CheckReentrancy throws InvalidOperationException(SR.Freezable_Reentrant) when the collection is modified (Clear, Insert, Remove, RemoveAt, Add) while a previous CollectionChanged notification is still being dispatched (_monitor.Busy). This prevents mutating the collection from inside a change handler, which would corrupt in-flight notifications for other listeners.
Solutions
- Defer the mutation out of the handler: Dispatcher.BeginInvoke(() => collection.Add(...)) or queue the change and apply after the notification completes.
- Restructure so handlers never mutate the same collection they are notified about.
- Use a snapshot (ToList()) inside the handler and mutate the copy, applying the result later.
Example fix
// before
void OnCollectionChanged(...) { collection.Remove(badItem); } // reentrant
// after
void OnCollectionChanged(...) { Dispatcher.BeginInvoke(new Action(() => collection.Remove(badItem))); } Defensive patterns
Strategy: try-catch
Validate before calling
bool canMutate = !isInsideCollectionChangedHandler; if (!canMutate) queueMutation(() => collection.Add(item));
Type guard
null
Try / catch
try { collection.Add(item); }
catch (InvalidOperationException ex) when (isReentrancy(ex)) { Dispatcher.BeginInvoke(new Action(() => collection.Add(item))); } Prevention
- Never mutate the collection inside its own CollectionChanged handler
- Defer mutations with Dispatcher.BeginInvoke or a pending-changes queue
- Keep handlers read-only; apply writes after the notification completes
When it happens
Trigger: Calling Add/Remove/Clear/etc. from inside a CollectionChanged event handler or a PropertyChanged handler triggered synchronously by the same collection change — e.g. handler does collection.Remove(item) while the Add notification is still propagating.
Common situations: Event handlers that 'fix up' the collection in response to a change, chained two-way data binding where updating one collection mutates another in the same notification pass, re-entrant UI logic in collection callbacks.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot pass multidimensional array to the CopyTo method on…
- DoubleKeyFrameCollection
- Event not found: Event 'eventName' not found on type…
- Int16KeyFrameCollection
- Int32KeyFrameCollection
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/67b66073de62d474.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/FreezableCollection.cs:933
/// {
/// CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item, index));
/// }
/// </code>
/// </remarks>
private IDisposable BlockReentrancy()
{
_monitor.Enter();
return _monitor;
}
/// <summary> Check and assert for reentrant attempts to change this collection. </summary>
/// <exception cref="InvalidOperationException"> raised when changing the collection
/// while another collection change is still being notified to other listeners </exception>
private void CheckReentrancy()
{
if (_monitor.Busy)
{
throw new InvalidOperationException(SR.Freezable_Reentrant);
}
}
#endregion ProtectedMethods
//------------------------------------------------------
//
// Internal Fields
//
//------------------------------------------------------
#region Internal Fields
internal List<T> _collection;
internal uint _version = 0;
#endregion Internal Fields
View on GitHub (pinned to 81131a70a4)