{"record":{"id":"20560d13eaa04f70","repo":"dotnet/wpf","slug":"sr-enumeratorversionchanged-journalentrystack","errorCode":null,"errorMessage":"SR.EnumeratorVersionChanged","messagePattern":"SR\\.EnumeratorVersionChanged","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Navigation/JournalEntryStack.cs","lineNumber":138,"sourceCode":"            }\n\n            _current = null;\n            return false;\n        }\n\n        public object Current\n        {\n            get { return _current; }\n        }\n\n        /// <summary>\n        /// Verifies that the journal has not been changed since this enumerator was created\n        /// </summary>\n        protected void VerifyUnchanged()\n        {\n            if (_version != _journal.Version)\n            {\n                throw new InvalidOperationException(SR.EnumeratorVersionChanged);\n            }\n        }\n\n        private Journal _journal;\n        private int _start;\n        private int _delta;\n        private int _next;\n        private JournalEntry _current;\n        private JournalEntryFilter _filter;\n        private int _version;\n    }\n\n    internal class LimitedJournalEntryStackEnumerable : IEnumerable, INotifyCollectionChanged\n    {\n        internal LimitedJournalEntryStackEnumerable(IEnumerable ieble)\n        {\n            _ieble = ieble;\n            INotifyCollectionChanged ichildnotify = ieble as INotifyCollectionChanged;","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Navigation/JournalEntryStack.cs#L120-L156","documentation":"The JournalEntryStack enumerator snapshots the journal's version when created; VerifyUnchanged (invoked from MoveNext) compares it against the journal's current version. If entries were added, removed, or the journal was navigated between enumerator creation and a MoveNext call, the enumerator is stale and InvalidOperationException (EnumeratorVersionChanged) is thrown, mirroring the classic 'collection was modified' guard.","triggerScenarios":"Enumerating a WPF navigation Journal's entry stack with foreach while navigation occurs (GoBack/GoForward/journal entries added or removed) on the same thread before the enumeration completes.","commonSituations":"UI code iterating back-stack entries while a NavigationService navigation (e.g. triggered by a button click or event handler inside the loop) mutates the journal; diagnostics/logging code walking the history while the user navigates.","solutions":["Materialize the entries into a list (ToList) before navigating, or complete the enumeration before triggering navigation.","Defer navigation out of the enumeration loop (Dispatcher.BeginInvoke) so mutation happens after MoveNext finishes.","If deferred enumeration is intended, re-create the enumerator after any journal change instead of continuing to use the stale one."],"exampleFix":"// before\nforeach (var entry in journal) // user clicks Back inside loop -> version changes\n{\n    Log(entry);\n    if (shouldGoBack) navService.GoBack();\n}\n// after\nvar snapshot = journal.ToList();\nforeach (var entry in snapshot) { Log(entry); }\nif (shouldGoBack) navService.GoBack();","handlingStrategy":"validation","validationCode":"bool journalUnchanged = journal.Version == enumeratorVersionAtCreation; // snapshot Version before enumerating","typeGuard":"bool CanEnumerate(Journal j, int capturedVersion) => j.Version == capturedVersion;","tryCatchPattern":"try { foreach (var e in journal) Process(e); }\ncatch (InvalidOperationException) { enumerator = journal.GetEnumerator(); /* restart */ }","preventionTips":["Snapshot the journal entries with ToList() before performing any navigation","Never navigate (GoBack/GoForward/Navigate) inside a foreach over journal entries","Defer navigation via Dispatcher.BeginInvoke until after enumeration completes"],"tags":["wpf","navigation","enumerator","collection-modified"],"backgroundTag":"collection-modified-during-enumeration","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}