{"record":{"id":"88780ec96d594225","repo":"dotnet/wpf","slug":"sr-timing-enumeratorinvalidated","errorCode":null,"errorMessage":"SR.Timing_EnumeratorInvalidated","messagePattern":"SR\\.Timing_EnumeratorInvalidated","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/TimelineClockCollection.cs","lineNumber":386,"sourceCode":"            /// <returns>\n            /// true if the enumerator was successfully advanced to the next\n            /// element; false if the enumerator has passed the end of the\n            /// collection.\n            /// </returns>\n            public bool MoveNext()\n            {\n                // If the collection is no longer empty, it means it was\n                // modified and we should thrown an exception. Otherwise, we\n                // are still valid, but the collection is empty so we should\n                // just return false.\n\n//                 _owner.VerifyAccess();\n\n                ClockGroup clockGroup = _owner as ClockGroup;\n\n                if (clockGroup != null && clockGroup.InternalChildren != null)\n                {\n                    throw new InvalidOperationException(SR.Timing_EnumeratorInvalidated);\n                }\n\n                return false;\n            }\n\n            #endregion // IEnumerator interface\n\n            #region Internal implementation\n\n            #region Data\n\n            private Clock   _owner;\n\n            #endregion // Data\n\n            #endregion // Internal implementation\n        }\n","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/TimelineClockCollection.cs#L368-L404","documentation":"Thrown by the ClockEnumerator's MoveNext when the clock tree owned by the collection has been invalidated during enumeration (the owner is a ClockGroup whose InternalChildren list is no longer null/valid). WPF invalidates the clock tree when its timing structure changes, so any enumerator outstanding from GetEnumerator becomes invalid. This mirrors the standard 'collection modified during enumeration' contract.","triggerScenarios":"Calling MoveNext (via foreach over a ClockGroup/ClockEnumerator) after the clock group's children collection was mutated or the clock tree was invalidated between obtaining the enumerator and advancing it.","commonSituations":"Iterating a ClockController/ClockGroup's clocks from a rendering or timing callback while animations are being added/removed or the storyboard hierarchy changes on another thread or during the same pass; holding an enumerator across animation tree rebuilds.","solutions":["Snapshot the clocks into a list (e.g. clockGroup.Children.ToList()) before iterating so enumeration does not depend on live internal state","Re-fetch a fresh enumerator after any change to the clock/storyboard tree instead of reusing the old one","Perform all clock-tree mutations and enumerations on the same thread and outside of active enumeration","Wrap iteration in try/catch for InvalidOperationException and restart enumeration with fresh state"],"exampleFix":"// before\nforeach (Clock clock in clockGroup)\n{\n    clock.ClockState = ...; // may mutate children\n}\n// after\nvar snapshot = clockGroup.Children.ToList();\nforeach (Clock clock in snapshot)\n{\n    ...\n}","handlingStrategy":"try-catch","validationCode":"var snapshot = clockGroup.Children != null ? clockGroup.Children.ToList() : new List<Clock>();","typeGuard":"bool canEnumerate(ClockGroup g) => g != null && g.InternalChildren == null;","tryCatchPattern":"try\n{\n    foreach (Clock c in clockGroup) { ... }\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"invalidated\"))\n{\n    // re-acquire enumerator and retry iteration\n}","preventionTips":["Snapshot the clock collection before iterating","Never hold clock enumerators across storyboard/clock-tree mutations","Enumerate and mutate the clock tree on the same thread"],"tags":["wpf","animation","enumeration","collection-modified"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}