dotnet/wpf · error · InvalidOperationException

SR.Format(SR.SetterOnStyleNotAllowedToHaveTarget…

Error message

SR.Format(SR.SetterOnStyleNotAllowedToHaveTarget, setter.TargetName)

What it means

Style Setters apply to the styled element itself; a Setter inside a Style must not specify TargetName, since styles have no child template nodes to target. ProcessSetters throws InvalidOperationException naming the offending TargetName when it is non-null.

Solutions

  1. Remove TargetName from the Setter; set the property directly on the styled element.
  2. If you need to target a named child, move the setter into a ControlTemplate's Triggers with the element defined in the template.
  3. Use Trigger.EnterActions/ExitActions with Storyboard.TargetName inside a template if animation targeting is required.

Example fix

<!-- before -->
<Style TargetType="Button">
  <Setter TargetName="textContent" Property="TextBlock.Foreground" Value="Red" />
</Style>
<!-- after -->
<ControlTemplate TargetType="Button">
  <Triggers>
    <Trigger Property="IsMouseOver" Value="True">
      <Setter TargetName="textContent" Property="TextBlock.Foreground" Value="Red" />
    </Trigger>
  </Triggers>
</ControlTemplate>
Defensive patterns

Strategy: validation

Validate before calling

foreach (Setter s in style.Setters.OfType<Setter>())
    if (s.TargetName != null)
        throw new InvalidOperationException($"Setter TargetName '{s.TargetName}' not allowed in a Style.");

Type guard

static bool StyleSetterValid(Setter s) => s.TargetName == null;

Try / catch

try { style.Seal(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("target")) { log.Error("Setter with TargetName in style", ex); }

Prevention

When it happens

Trigger: A Setter with TargetName="..." placed in Style.Setters (legal only in ControlTemplate/FrameworkTemplate triggers or Template.Setters).

Common situations: Copying a setter from a ControlTemplate.Triggers block (which legitimately uses TargetName) back into Style.Triggers/Setters; XAML where <Setter TargetName="partName"> was written inside a Style instead of inside a template trigger.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Style.cs:630

            {
                PropertyValues = new FrugalStructList<System.Windows.PropertyValue>(style.Setters.Count);
            }

            // Add EventSetters to local EventHandlersStore
            for (int i = 0; i < style.Setters.Count; i++)
            {
                SetterBase setterBase = style.Setters[i];
                Debug.Assert(setterBase != null, "Setter collection must contain non-null instances of SetterBase");

                // Setters are folded into the PropertyValues table only for the current style. The
                // processing of BasedOn Style properties will occur in subsequent call to ProcessSelfStyle
                Setter setter = setterBase as Setter;
                if (setter != null)
                {
                    // Style Setters are not allowed to have a child target name - since there are no child nodes in a Style.
                    if( setter.TargetName != null )
                    {
                        throw new InvalidOperationException(SR.Format(SR.SetterOnStyleNotAllowedToHaveTarget, setter.TargetName));
                    }

                    if (style == this)
                    {
                        DynamicResourceExtension dynamicResource = setter.ValueInternal as DynamicResourceExtension;
                        if (dynamicResource == null)
                        {
                            UpdatePropertyValueList( setter.Property, PropertyValueType.Set, setter.ValueInternal );
                        }
                        else
                        {
                            UpdatePropertyValueList( setter.Property, PropertyValueType.Resource, dynamicResource.ResourceKey );
                        }
                    }
                }
                else
                {

View on GitHub (pinned to 81131a70a4)