dotnet/wpf · error · ArgumentOutOfRangeException

SR.RelativeSourceInvalidAncestorLevel

Error message

SR.RelativeSourceInvalidAncestorLevel

What it means

Assigning an AncestorLevel less than 1 to a RelativeSource throws ArgumentOutOfRangeException. AncestorLevel counts ancestor levels (1 = nearest ancestor), so 0 or negative levels are meaningless in FindAncestor mode and the setter treats them as an invalid argument.

Solutions

  1. Use AncestorLevel >= 1 in FindAncestor mode
  2. Clamp computed levels with Math.Max(1, level)
  3. Use AncestorType=null semantics instead of 0 if you meant 'no restriction'

Example fix

// before
rs.AncestorLevel = 0; // throws in FindAncestor mode
// after
rs.AncestorLevel = 1;
Defensive patterns

Strategy: validation

Validate before calling

int lvl = Math.Max(1, computedLevel);
rs.AncestorLevel = lvl;

Try / catch

try { rs.AncestorLevel = n; }
catch (ArgumentOutOfRangeException) { rs.AncestorLevel = 1; }

Prevention

When it happens

Trigger: Setting RelativeSource.AncestorLevel to 0 or a negative value while _mode == FindAncestor (note: 0 is allowed only to clear it in non-FindAncestor modes).

Common situations: Computed level expressions evaluating to 0; XAML AncestorLevel="0"; loop counters that decrement below 1 when climbing ancestors.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

        /// setting AncestorLevel will implicitly lock Mode to FindAncestor. </remarks>
        /// <exception cref="InvalidOperationException"> RelativeSource is not in FindAncestor mode </exception>
        /// <exception cref="ArgumentOutOfRangeException"> AncestorLevel cannot be set to less than 1 </exception>
        public int AncestorLevel
        {
            get { return _ancestorLevel; }
            set
            {
                Debug.Assert((!IsUninitialized) || (_mode == RelativeSourceMode.FindAncestor));

                if (_mode != RelativeSourceMode.FindAncestor)
                {
                    // in all other modes, AncestorLevel should not get set to a non-zero value
                    if (value != 0)
                        throw new InvalidOperationException(SR.RelativeSourceNotInFindAncestorMode);
                }
                else if (value < 1)
                {
                    throw new ArgumentOutOfRangeException(SR.RelativeSourceInvalidAncestorLevel);
                }
                else
                {
                    _ancestorLevel = value;
                }
            }
        }

        /// <summary>
        /// This method is used by TypeDescriptor to determine if this property should
        /// be serialized.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeAncestorLevel()
        {
            return (_mode == RelativeSourceMode.FindAncestor);
        }

View on GitHub (pinned to 81131a70a4)