dotnet/wpf · error · InvalidOperationException

SR.RelativeSourceModeIsImmutable

Error message

SR.RelativeSourceModeIsImmutable

What it means

RelativeSource.Mode is immutable once the object has been initialized. Attempting to change Mode to a different value after initialization throws InvalidOperationException; only setting it while still uninitialized (IsUninitialized) is allowed.

Solutions

  1. Create a new RelativeSource instance with the desired mode instead of mutating
  2. Set Mode only before the source is used/initialized
  3. Freeze/share per-mode RelativeSource instances (they are intended to be immutable after setup)

Example fix

// before
rs.Mode = RelativeSourceMode.Self; // throws if rs initialized as FindAncestor
// after
var newRs = new RelativeSource(RelativeSourceMode.Self);
Defensive patterns

Strategy: validation

Validate before calling

// decide the mode before first use; never rewrite it later
var rs = new RelativeSource(desiredMode);

Try / catch

try { rs.Mode = newMode; }
catch (InvalidOperationException) { rs = new RelativeSource(newMode); }

Prevention

When it happens

Trigger: Setting RelativeSource.Mode after EndInit/first use with a value different from the current _mode; reusing one RelativeSource instance across bindings with different modes.

Common situations: Recycling a shared RelativeSource between bindings; mutating a Mode declared in XAML from code-behind after load; data-trigger/style code that rewrites the mode at runtime.

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/dba149e38b6dc508. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/RelativeSource.cs:154

        /// <summary>mode of RelativeSource
        /// </summary>
        /// <remarks> Mode is read-only after initialization.
        /// If Mode is not set explicitly, setting AncestorType or AncestorLevel will implicitly lock the Mode to FindAncestor. </remarks>
        /// <exception cref="InvalidOperationException"> RelativeSource Mode is immutable after initialization;
        /// instead of changing the Mode on this instance, create a new RelativeSource or use a different static instance. </exception>
        [ConstructorArgument("mode")]
        public RelativeSourceMode Mode
        {
            get { return _mode; }
            set
            {
                if (IsUninitialized)
                {
                    InitializeMode(value);
                }
                else if (value != _mode)    // mode changes are not allowed
                {
                    throw new InvalidOperationException(SR.RelativeSourceModeIsImmutable);
                }
            }
        }

        /// <summary> The Type of ancestor to look for, in FindAncestor mode.
        /// </summary>
        /// <remarks> if Mode has not been set explicitly, setting AncestorType will implicitly lock Mode to FindAncestor. </remarks>
        /// <exception cref="InvalidOperationException"> RelativeSource is not in FindAncestor mode </exception>
        public Type AncestorType
        {
            get { return _ancestorType; }
            set
            {
                if (IsUninitialized)
                {
                    Debug.Assert(_mode == RelativeSourceMode.FindAncestor);
                    AncestorLevel = 1;  // lock the mode and set default level
                }

View on GitHub (pinned to 81131a70a4)