{"record":{"id":"8c63e66b46209730","repo":"dotnet/wpf","slug":"sr-sourcechangeexpressionmismatch","errorCode":null,"errorMessage":"SR.SourceChangeExpressionMismatch","messagePattern":"SR\\.SourceChangeExpressionMismatch","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyObject.cs","lineNumber":1039,"sourceCode":"            object value = entry.IsCoercedWithCurrentValue ? entry.ModifiedValue.CoercedValue : entry.LocalValue;\n            return !object.ReferenceEquals(value, DependencyProperty.UnsetValue);\n        }\n\n        //\n        // Changes the sources of an existing Expression\n        //\n        internal static void ChangeExpressionSources(Expression expr, DependencyObject d, DependencyProperty dp, DependencySource[] newSources)\n        {\n            if (!expr.ForwardsInvalidations)\n            {\n                // Get current local value (should be provided Expression)\n                // (No need to go through read local callback, just checking\n                // for presence of Expression)\n                EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex);\n\n                if (!entryIndex.Found || (d._effectiveValues[entryIndex.Index].LocalValue != expr))\n                {\n                    throw new ArgumentException(SR.SourceChangeExpressionMismatch);\n                }\n            }\n\n            // Get current sources\n            // CALLBACK\n            DependencySource[] currentSources = expr.GetSources();\n\n            // Remove old\n            if (currentSources != null)\n            {\n                UpdateSourceDependentLists(d, dp, currentSources, expr, false);  // Remove\n            }\n\n            // Add new\n            if (newSources != null)\n            {\n                UpdateSourceDependentLists(d, dp, newSources, expr, true);  // Add\n            }","sourceCodeStart":1021,"sourceCodeEnd":1057,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyObject.cs#L1021-L1057","documentation":"Thrown by DependencyObject.ChangeExpressionSources when the local value stored on the target DependencyObject is no longer the Expression instance whose sources are being re-evaluated. The property system detected a mismatch between the expression it was asked to re-source and the actual local value, indicating the expression was replaced or cleared concurrently or out of order.","triggerScenarios":"Calling SetValue with an Expression, then modifying its sources via ChangeExpressionSources when the local value slot no longer reference-equals that expression; re-entrancy or double-set of expressions on the same property.","commonSituations":"Custom binding/expression implementations that call ChangeExpressionSources after the expression was overwritten, race conditions between expression replacement and source updates, misuse of internal expression APIs.","solutions":["Verify the expression is still the current local value (ReadLocalValue) before changing its sources","Re-set the expression with SetValue instead of calling ChangeExpressionSources on a stale instance","Guard against re-entrant property changes while updating expression sources","Use standard Binding/BindingExpression APIs rather than raw Expression plumbing"],"exampleFix":"// before\nexpr.ChangeSources(d, dp, newSources); // stale expr\n// after\nif (ReferenceEquals(d.ReadLocalValue(dp), expr)) { expr.ChangeSources(d, dp, newSources); }","handlingStrategy":"validation","validationCode":"if (!ReferenceEquals(d.ReadLocalValue(dp), expr)) throw new InvalidOperationException(\"Expression no longer current\");\nexpr.ChangeSources(d, dp, sources);","typeGuard":"static bool IsCurrentExpression(DependencyObject d, DependencyProperty dp, Expression expr) => ReferenceEquals(d.ReadLocalValue(dp), expr);","tryCatchPattern":"try { expr.ChangeSources(d, dp, sources); }\ncatch (ArgumentException) { d.SetValue(dp, expr); /* re-install then retry */ }","preventionTips":["Verify ReadLocalValue still returns your expression before source changes","Avoid replacing expressions and changing sources concurrently","Prefer standard Binding APIs over custom Expression plumbing"],"tags":["wpf","dependency-property","expression"],"backgroundTag":"internal-invariant-violation","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"}