AvaloniaUI/Avalonia · error · InvalidOperationException

ControlTemplate styles cannot contain multiple template sele

Error message

ControlTemplate styles cannot contain multiple template selectors.

What it means

Thrown during ValidateNestingSelector when a selector chain inside a ControlTheme contains more than one TemplateSelector. A ControlTheme can only enter its control's template once; chaining multiple `:template()` steps is structurally invalid because there is no nested template to enter.

Source

Thrown at src/Avalonia.Base/Styling/Selector.cs:121

        /// </summary>
        private protected abstract Selector? MovePrevious();

        /// <summary>
        /// Moves to the previous selector or the parent selector.
        /// </summary>
        private protected abstract Selector? MovePreviousOrParent();

        internal virtual void ValidateNestingSelector(bool inControlTheme, int templateCount = 0)
        {
            var s = this;

            if (inControlTheme)
            {
                if (!s.InTemplate && s.IsCombinator)
                    throw new InvalidOperationException(
                        "ControlTheme style may not directly contain a child or descendent selector.");
                if (s is TemplateSelector && templateCount++ > 0)
                    throw new InvalidOperationException(
                        "ControlTemplate styles cannot contain multiple template selectors.");
            }

            var previous = s.MovePreviousOrParent();

            if (previous is null)
            {
                if (s is not NestingSelector)
                    throw new InvalidOperationException("Child styles must have a nesting selector.");
            }
            else
            {
                previous.ValidateNestingSelector(inControlTheme, templateCount);
            }
        }

        private static SelectorMatch MatchUntilCombinator(
            StyledElement control,

View on GitHub (pinned to 11c5427268)

Solutions

  1. Use exactly one Template selector per ControlTheme selector chain; address deeper parts with child/descendant combinators after the single `:template()`.
  2. If you need to style a nested templated control, define a separate ControlTheme for that control type instead of chaining template selectors.

Example fix

// before (two template selectors)
new Style(s => s.OfType<Button>().Template().OfType<ContentPresenter>().Template().OfType<TextBlock>())

// after (single template, then descendant)
new Style(s => s.OfType<Button>().Template().Descendant().OfType<TextBlock>())
Defensive patterns

Strategy: validation

Validate before calling

// Count Template selectors in the chain; reject if > 1 before assigning.
int CountTemplates(Selector? s)
{
    int n = 0;
    while (s is not null) { if (s is TemplateSelector) n++; s = s.MoveNextPrevious(); }
    return n;
}

Prevention

When it happens

Trigger: Writing a selector like `Button /template/ ContentPresenter /template/ TextBlock` inside a ControlTheme. The counter increments on the first TemplateSelector and the second triggers the throw.

Common situations: Assuming template parts have their own templates that can be re-entered; copy-pasting a template selector segment; building selectors programmatically and concatenating two Template() calls.

Related errors


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