dotnet/wpf · error · InvalidOperationException

SR.Format(SR.BindingExpressionStatusChanged, _status…

Error message

SR.Format(SR.BindingExpressionStatusChanged, _status, status)

What it means

SetStatus is the single mutation point for a binding expression's internal status. Once an expression is Detached (removed from its binding target), its status is frozen; attempting to transition to any different status throws this InvalidOperationException, preventing post-detach state corruption. The message includes the current status and the requested one.

Solutions

  1. Do not reuse BindingExpression objects after detach; create a new Binding and call SetBinding again.
  2. Ensure UpdateSource/UpdateTarget calls only happen while the binding is attached (check expression.IsDetached first).
  3. If holding references to BindingExpressionBase, null them out on Unloaded/Detached events instead of reusing them.

Example fix

// before
var expr = (BindingExpression)textBox.GetBindingExpression(TextBox.TextProperty);
// ... element detached ...
expr.UpdateSource(); // throws

// after
var expr = (BindingExpression)textBox.GetBindingExpression(TextBox.TextProperty);
if (expr != null && !expr.IsDetached) expr.UpdateSource();
Defensive patterns

Strategy: type-guard

Type guard

bool CanUpdate(BindingExpressionBase expr) => expr != null && !expr.IsDetached;

Try / catch

try { expr.UpdateSource(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("status"))
{
    // expression detached; recreate binding
}

Prevention

When it happens

Trigger: Calling SetStatus with a status different from the current one on an expression whose IsDetached is true — typically from reactivating, transferring, or updating a BindingExpressionBase after Detach (e.g. reusing a BindingExpression whose target property or element was cleared).

Common situations: Reusing binding expression objects across element re-templating; updating a binding after the element was removed from the visual tree; custom code or third-party frameworks that poke at binding internals during unload.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/f115f8ad1925c4b3. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingExpressionBase.cs:2106

            {
                // set IEnumerable properties (e.g. ItemsSource) to null, so that
                // the control can disconnect from the individual items
                newValue = null;
            }

            // notify the target property about the new value (cheaply)
            if (newValue != DependencyProperty.UnsetValue)
            {
                ChangeValue(newValue, false);
                Invalidate(false);
            }
        }

        internal void SetStatus(BindingStatusInternal status)
        {
            if (IsDetached && status != _status)
            {
                throw new InvalidOperationException(SR.Format(SR.BindingExpressionStatusChanged, _status, status));
            }

            _status = status;
        }

        // convert a user-supplied fallback value to a usable equivalent
        //  returns:    UnsetValue          if user did not supply a fallback value
        //              value               if fallback value is legal
        //              DefaultValueObject  otherwise
        internal static object ConvertFallbackValue(object value, DependencyProperty dp, object sender)
        {
            Exception e;
            object result = ConvertValue(value, dp, out e);

            if (result == DefaultValueObject)
            {
                if (TraceData.IsEnabled)
                {

View on GitHub (pinned to 81131a70a4)