dotnet/wpf · error · InvalidOperationException
SR.TemplateFindNameInInvalidElement
Error message
SR.TemplateFindNameInInvalidElement
What it means
Template.FindName throws InvalidOperationException (SR.TemplateFindNameInInvalidElement) when the templatedParent argument is not an element instantiated BY this specific template (i.e. templatedParent.TemplateInternal != this). Names inside a template's namescope are only resolvable through the template that created that scope.
Solutions
- Pass the control that is actually templated by this template instance: use control.Template (or FrameworkElement.FindName directly on it).
- Prefer element.FindName(name) or NameScope.GetNameScope on the templated child instead of raw template.FindName.
- Ensure the template reference used for FindName is the same instance as control.Template, not a resource lookup that yields a different copy.
Example fix
// before
var tpl = (ControlTemplate)Application.Current.Resources["tpl"];
var tb = (TextBlock)tpl.FindName("text", myButton); // throws: myButton.TemplateInternal != tpl
// after
var tb = (TextBlock)myButton.Template.FindName("text", myButton); Defensive patterns
Strategy: validation
Validate before calling
if (ReferenceEquals(templatedParent?.TemplateInternal, template))
var found = template.FindName(name, templatedParent); Type guard
static bool OwnsTemplate(FrameworkTemplate t, FrameworkElement e) => ReferenceEquals(e?.TemplateInternal, t);
Try / catch
try { return template.FindName(name, element); }
catch (InvalidOperationException) { return element?.FindName(name); } Prevention
- Use control.Template (the live instance) for FindName, not a separate resource lookup.
- Prefer element.FindName for simple lookups inside templates.
- Re-fetch the template after a theme change that re-applies templates.
When it happens
Trigger: Calling template.FindName(name, element) where element's TemplateInternal is a different template instance — e.g. the element uses another template, the template was re-applied (so the instance is stale), or the caller passes the wrong element (a plain content child rather than a templated child).
Common situations: Passing a Window/UserControl instead of the templated control; retrieving a template from Application resources but searching within a control that uses a copied/retemplated instance; control template re-applied after theme change leaving a stale template reference.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- SR.Format(SR.VisualTreeRootIsFrameworkElement…
- SR.FlowDocumentScrollViewerDocumentBelongsToAnotherFlowDocum…
- SR.CannotMoveToUnknownPosition
- SR.ChildTemplateInstanceDoesNotExist
- SR.ElementMustBelongToTemplate
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/5866fc883e5127d6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkTemplate.cs:304
/// <summary>
/// FindName - Finds the element associated with the id defined under this control template.
/// Context of the FrameworkElement where this template is applied will be passed
/// as parameter.
/// </summary>
/// <param name="name">string name</param>
/// <param name="templatedParent">context where this template is applied</param>
/// <returns>the element associated with the Name</returns>
public Object FindName(string name, FrameworkElement templatedParent)
{
// Verify Context Access
VerifyAccess();
ArgumentNullException.ThrowIfNull(templatedParent);
if (this != templatedParent.TemplateInternal)
{
throw new InvalidOperationException(SR.TemplateFindNameInInvalidElement);
}
return StyleHelper.FindNameInTemplateContent(templatedParent, name, this);
}
#endregion PublicProperties
#region INameScope
/// <summary>
/// Registers the name - Context combination
/// </summary>
/// <param name="name">Name to register</param>
/// <param name="scopedElement">Element where name is defined</param>
public void RegisterName(string name, object scopedElement)
{
// Verify Context AccessView on GitHub (pinned to 81131a70a4)