dotnet/wpf · error · InvalidOperationException

SR.ChildTemplateInstanceDoesNotExist

Error message

SR.ChildTemplateInstanceDoesNotExist

What it means

While invalidating a property on a style-created child (InvalidatePropertyOnTemplateFetch-style path), GetChild returned null for the requested childIndex, meaning no template instance exists under that index. WPF throws InvalidOperationException (ChildTemplateInstanceDoesNotExist) because a property cannot be pushed to a child that was never instantiated.

Solutions

  1. Verify the named child still exists in the template for every Trigger/Setters TargetName
  2. Ensure the template has been applied (element is loaded) before invalidating child properties
  3. Do not mutate template children from code; change templates/styles instead
  4. Null-check before invalidation in custom code that walks template children

Example fix

// before
child = StyleHelper.GetChild(styledChildren, childIndex);
StyleHelper.InvalidatePropertyOnTemplateFetch(...); // may throw if child removed
// after
child = StyleHelper.GetChild(styledChildren, childIndex);
if (child != null) { /* proceed with invalidation */ } else { return; }
Defensive patterns

Strategy: try-catch

Validate before calling

bool ChildInstanceExists(FrameworkElement parent, int childIndex)
{
    var child = VisualTreeHelper.GetChild(parent, childIndex);
    return child != null;
}

Try / catch

try { InvalidateChildProperty(childIndex); }
catch (InvalidOperationException ex) when (ex.Message.Contains("instance does not exist"))
{ ReapplyTemplate(); /* template children were torn down */ }

Prevention

When it happens

Trigger: A Style value/trigger change targeting childIndex whose element was never created (template not yet applied, child conditionally removed); invalidation racing template teardown; corrupted styledChildren state after the tree was modified externally.

Common situations: Removing named children from a template at runtime while triggers still reference them; applying styles before the template has instantiated children; race between dispatcher operations that invalidate properties and template re-application.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs:4086

                    DependencyObject child = null;
                    DependencyProperty invalidProperty = resourceDependents[i].Property;

                    int childIndex = resourceDependents[i].ChildIndex;
                    if (childIndex == 0)
                    {
                        // Index '0' means 'self' (container)
                        child = container;
                    }
                    else if (invalidateVisualTreeToo)
                    {
                        Debug.Assert(styledChildren != null, "Should reach here only if the template tree has already been created");

                        // Locate child to invalidate
                        child = GetChild(styledChildren, childIndex);

                        if (child == null)
                        {
                            throw new InvalidOperationException(SR.ChildTemplateInstanceDoesNotExist);
                        }
                    }

                    if (child != null)
                    {
                        // Invalidate property on child
                        child.InvalidateProperty(invalidProperty);

                        // skip remaining dependents for the same property - we only
                        // need to invalidate once.  The list is sorted, so we just need
                        // to skip until we find a new property.
                        int dpIndex = invalidProperty.GlobalIndex;
                        while (++i < resourceDependents.Count)
                        {
                            if (resourceDependents[i].ChildIndex != childIndex ||
                                resourceDependents[i].Property.GlobalIndex != dpIndex)
                            {
                                break;

View on GitHub (pinned to 81131a70a4)