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
- Use AncestorLevel >= 1 in FindAncestor mode
- Clamp computed levels with Math.Max(1, level)
- 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
- Clamp AncestorLevel to >= 1
- Avoid AncestorLevel="0" in FindAncestor XAML
- Guard computed levels against underflow
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
- SR.ItemCollectionRemoveArgumentOutOfRange
- SR.RelativeSourceModeIsImmutable
- SR.RelativeSourceNeedsAncestorType
- SR.RelativeSourceNeedsMode
- SR.RelativeSourceNotInFindAncestorMode
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)