AvaloniaUI/Avalonia · error · InvalidOperationException

BindingExpression was already attached to a different proper

Error message

BindingExpression was already attached to a different property.

What it means

AttachCore rejects attaching an already-attached expression to a different AvaloniaProperty than the one it was first bound to. A binding expression is tied to one target property; switching properties indicates a logic error or accidental reuse.

Source

Thrown at src/Avalonia.Base/Data/Core/UntypedBindingExpressionBase.cs:269

    /// possible.
    /// </summary>
    /// <param name="value">The value to write.</param>
    /// <returns>
    /// True if the value could be written to the binding source; otherwise false.
    /// </returns>
    internal virtual bool WriteValueToSource(object? value) => false;

    private void AttachCore(
        IBindingExpressionSink sink,
        ImmediateValueFrame? frame,
        AvaloniaObject target,
        AvaloniaProperty? targetProperty,
        BindingPriority priority)
    {
        if (_sink is not null)
            throw new InvalidOperationException("BindingExpression was already attached.");
        if (TargetProperty is not null && TargetProperty != targetProperty)
            throw new InvalidOperationException("BindingExpression was already attached to a different property.");

        _sink = sink;
        _frame = frame;
        _target = new(target);
        TargetProperty = targetProperty;
        TargetType = targetProperty?.PropertyType ?? typeof(object);
        Priority = priority;
    }


    /// <summary>
    /// Converts a value using a value converter, logging a warning if necessary.
    /// </summary>
    /// <param name="converter">The value converter.</param>
    /// <param name="converterCulture">The culture to use for the conversion.</param>
    /// <param name="converterParameter">The converter parameter.</param>
    /// <param name="value">The value to convert.</param>
    /// <param name="targetType">The target type to convert to.</param>

View on GitHub (pinned to 11c5427268)

Solutions

  1. Create a new expression instance per target property via CreateInstance.
  2. Ensure each control+property pair gets its own expression; never reuse one instance across properties.
  3. Audit caching layers that hand out the same expression to multiple property bindings.

Example fix

// before:
expr.Attach(..., PropertyA, ...);
expr.Attach(..., PropertyB, ...); // throws

// after:
var exprA = binding.CreateInstance(t, PropertyA, anchor);
var exprB = binding.CreateInstance(t, PropertyB, anchor);
Defensive patterns

Strategy: validation

Validate before calling

// One expression per (target, property) pair.
var exprA = binding.CreateInstance(t, PropertyA, anchor);
var exprB = binding.CreateInstance(t, PropertyB, anchor);

Prevention

When it happens

Trigger: Attaching the same binding expression instance to target property A, then later to target property B (where TargetProperty was already recorded as A).

Common situations: Sharing one expression object across two different properties, or rebinding a detached-looking (but not actually detached) expression to a new property.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/43bc044f2cc7c01c. Report an issue: GitHub.