dotnet/wpf · error · InvalidOperationException
SR.Format(SR.ChildNameNamePatternReserved, _childName)
Error message
SR.Format(SR.ChildNameNamePatternReserved, _childName)
What it means
FrameworkElementFactory.Seal() validates the factory's ChildName against a reserved naming pattern (names starting with a reserved prefix used internally by the template system). If the child name is present but fails IsChildNameValid (it matches a reserved pattern, e.g. begins with a character/sequence the framework reserves for its own name scope bookkeeping), Seal throws InvalidOperationException. Seal is invoked when the factory is used by a template, so the error surfaces at template compile/seal time, not at factory construction.
Solutions
- Choose a different child name that passes IsChildNameValid (avoid the reserved prefix pattern; use ordinary alphanumeric names).
- If the name is only for element lookup, use FindName-compatible names and set Name via the factory constructor FrameworkElementFactory(Type, String) with a valid string.
- If the name came from user input or an external config, sanitize/validate it before assigning to factory.Name.
Example fix
// before var factory = new FrameworkElementFactory(typeof(Button)); factory.Name = "$reservedName"; // reserved pattern // after var factory = new FrameworkElementFactory(typeof(Button)); factory.Name = "myButton"; // valid, non-reserved name
Defensive patterns
Strategy: validation
Validate before calling
if (!string.IsNullOrEmpty(factory.Name) && (factory.Name.StartsWith("$") || factory.Name.Contains(":")))
throw new ArgumentException($"Child name '{factory.Name}' uses a reserved pattern"); Type guard
bool IsValidChildName(string n) => string.IsNullOrEmpty(n) || !(n.StartsWith("$") || n.Contains(':')); Try / catch
try { template.Seal(); } catch (InvalidOperationException ex) when (ex.Message.Contains("reserved")) { /* pick a different child name */ } Prevention
- Use plain alphanumeric names for factory children
- Never feed external/user-supplied identifiers straight into factory.Name
- Sanitize names before constructing the factory tree
When it happens
Trigger: Setting FrameworkElementFactory.Name (which sets _childName) to a string that fails IsChildNameValid — i.e. a name matching the reserved pattern — and then using the factory in a DataTemplate/ControlTemplate so Seal() runs.
Common situations: Programmatically building templates in code and assigning a child name that collides with WPF's reserved name syntax instead of an ordinary XAML name; copy-pasting generated names from other systems (e.g. '$Name', ':0') into factory names.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- SR.FrameworkElementFactoryMustBeSealed
- Cannot reopen a popup in the closed event handler.
- Decorator marked as PART_ContentHost must have no content.
- InvalidOperationException (no message)
- Only Decorator and ScrollViewer can be used as…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/4e852b3bf27401c9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElementFactory.cs:564
if (_firstChild != null)
{
// This factory has children, it must implement IAddChild so that these
// children can be added to the logical tree
if (!typeof(IAddChild).IsAssignableFrom(_type))
{
throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild, _type.Name));
}
}
ApplyAutoAliasRules();
if ((_childName != null) && (_childName != String.Empty))
{
// ChildName provided
if (!IsChildNameValid(_childName))
{
throw new InvalidOperationException(SR.Format(SR.ChildNameNamePatternReserved, _childName));
}
_childName = String.Intern(_childName);
}
else
{
// ChildName not provided
_childName = GenerateChildName();
}
lock (_synchronized)
{
// Set delayed ChildID for all property triggers
for (int i = 0; i < PropertyValues.Count; i++)
{
PropertyValue propertyValue = PropertyValues[i];View on GitHub (pinned to 81131a70a4)