{"record":{"id":"5157bca64d0ced40","repo":"dotnet/wpf","slug":"sr-localvalueenumerationinvalidated","errorCode":null,"errorMessage":"SR.LocalValueEnumerationInvalidated","messagePattern":"SR\\.LocalValueEnumerationInvalidated","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyObject.cs","lineNumber":3114,"sourceCode":"            return new EntryIndex(iLo, found: false);\n        }\n\n        // insert the given entry at the given index\n        // this function assumes that entryIndex is at the right\n        // location such that the resulting list remains sorted by EffectiveValueEntry.PropertyIndex\n        private void InsertEntry(EffectiveValueEntry entry, uint entryIndex)\n        {\n            // For thread-safety, sealed DOs can't modify _effectiveValues.\n            Debug.Assert(!DO_Sealed, \"A Sealed DO cannot be modified\");\n\n#if DEBUG\n            EntryIndex debugIndex = LookupEntry(entry.PropertyIndex);\n            Debug.Assert(!debugIndex.Found && debugIndex.Index == entryIndex, \"Inserting duplicate\");\n#endif\n\n            if (!CanModifyEffectiveValues)\n            {\n                throw new InvalidOperationException(SR.LocalValueEnumerationInvalidated);\n            }\n\n            uint effectiveValuesCount = EffectiveValuesCount;\n            if (effectiveValuesCount > 0)\n            {\n                if (_effectiveValues.Length == effectiveValuesCount)\n                {\n                    int newSize = (int) (effectiveValuesCount * (IsInPropertyInitialization ? 2.0 : 1.2));\n                    if (newSize == effectiveValuesCount)\n                    {\n                        newSize++;\n                    }\n\n                    EffectiveValueEntry[] destEntries = new EffectiveValueEntry[newSize];\n                    Array.Copy(_effectiveValues, 0, destEntries, 0, entryIndex);\n                    destEntries[entryIndex] = entry;\n                    Array.Copy(_effectiveValues, entryIndex, destEntries, entryIndex + 1, effectiveValuesCount - entryIndex);\n                    _effectiveValues = destEntries;","sourceCodeStart":3096,"sourceCodeEnd":3132,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyObject.cs#L3096-L3132","documentation":"Thrown by SetEffectiveValue when the DependencyObject's effective-value table cannot be modified because an enumeration over LocalValueDictionary is in progress (CanModifyEffectiveValues == false). Modifying local values during that enumeration would corrupt the enumerator, so the property system blocks it.","triggerScenarios":"Calling SetValue/ClearValue on a DependencyObject from inside a foreach over its ReadLocalValues / LocalValueDictionary on the same object; re-entrant property changes triggered from a local-value enumerator callback.","commonSituations":"Iterating local values to reset them and clearing inside the loop, diagnostics/logging code enumerating values while bindings update them, re-entrancy from value-change handlers fired during enumeration.","solutions":["Snapshot the enumerated entries (ToList()/ToArray()) first, then modify values after the loop ends","Defer SetValue/ClearValue via Dispatcher.BeginInvoke if changes must happen during enumeration","Restructure code so enumeration and mutation target different DependencyObjects","Lock or single-thread the mutation path to avoid re-entrancy"],"exampleFix":"// before\nforeach (var e in obj.ReadLocalValues()) { obj.ClearValue(e.Key); } // throws\n// after\nforeach (var e in obj.ReadLocalValues().ToList()) { obj.ClearValue(e.Key); }","handlingStrategy":"try-catch","validationCode":"if (!obj.CanModifyEffectiveValues) {\n    pendingChanges.Add(() => obj.SetValue(dp, value)); // defer\n} else { obj.SetValue(dp, value); }","typeGuard":null,"tryCatchPattern":"try { obj.SetValue(dp, value); }\ncatch (InvalidOperationException) when (isEnumeratingLocalValues) { obj.Dispatcher.BeginInvoke(() => obj.SetValue(dp, value)); }","preventionTips":["Never call SetValue/ClearValue inside foreach over ReadLocalValues","Snapshot enumerations with ToList/ToArray first","Defer mutations triggered during enumeration via Dispatcher or a queue"],"tags":["wpf","dependency-property","enumeration"],"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"}