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

  1. Choose a different child name that passes IsChildNameValid (avoid the reserved prefix pattern; use ordinary alphanumeric names).
  2. 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.
  3. 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

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


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)