{"record":{"id":"e62b3d800c2fb48d","repo":"dotnet/wpf","slug":"sr-localvalueenumerationreset","errorCode":null,"errorMessage":"SR.LocalValueEnumerationReset","messagePattern":"SR\\.LocalValueEnumerationReset","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/LocalValueEnumerator.cs","lineNumber":70,"sourceCode":"        /// <summary>\n        ///     Determine inequality\n        /// </summary>\n        public static bool operator !=(LocalValueEnumerator obj1, LocalValueEnumerator obj2)\n        {\n          return !(obj1 == obj2);\n        }\n        \n        /// <summary>\n        ///     Get current entry\n        /// </summary>\n        public LocalValueEntry Current\n        {\n            get\n            {\n                if(_index == -1 )\n                {\n                    // IEnumerator.Current is documented to throw this exception\n                    throw new InvalidOperationException(SR.LocalValueEnumerationReset);\n                }\n\n                if(_index >= Count )\n                {\n                    // IEnumerator.Current is documented to throw this exception\n                    throw new InvalidOperationException(SR.LocalValueEnumerationOutOfBounds);\n                }\n                \n                return _snapshot[_index];\n            }\n        }\n\n        /// <summary>\n        ///     Get current entry (object reference based)\n        /// </summary>\n        object IEnumerator.Current\n        {\n            get { return Current; }","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/LocalValueEnumerator.cs#L52-L88","documentation":"LocalValueEnumerator.Current throws InvalidOperationException(SR.LocalValueEnumerationReset) when the enumerator has not been started (MoveNext never called, index still -1). This matches the IEnumerator.Current contract documented in .NET. Accessing Current before starting enumeration is a caller sequencing error.","triggerScenarios":"Obtaining a LocalValueEnumerator from DependencyObject.GetLocalValueEnumerator() and reading Current before the first MoveNext() call.","commonSituations":"Manual foreach-free iteration loops that forget the initial MoveNext; refactored code where the MoveNext call was removed or reordered; generic enumerator wrappers calling Current eagerly.","solutions":["Call MoveNext() at least once before reading Current.","Prefer a foreach loop over the enumerator, which handles sequencing automatically.","Restructure the loop to only access Current after MoveNext() returns true.","Catch InvalidOperationException as a last resort, but fix the loop ordering instead."],"exampleFix":"// before\nvar e = obj.GetLocalValueEnumerator();\nvar entry = e.Current; // throws: not started\n// after\nvar e = obj.GetLocalValueEnumerator();\nwhile (e.MoveNext())\n{\n    var entry = e.Current;\n}","handlingStrategy":"validation","validationCode":"bool ready = enumerator.MoveNext(); // only read Current if this returned true","typeGuard":"null","tryCatchPattern":"try { var cur = enumerator.Current; }\ncatch (InvalidOperationException) { /* enumerator not started; call MoveNext first */ }","preventionTips":["Always call MoveNext() before reading Current.","Prefer foreach over manual enumerator use.","Never dereference Current outside a MoveNext-checked loop."],"tags":["wpf","enumerator","invalid-operation"],"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-22T01:17:13.364Z"}