dotnet/wpf · error · InvalidOperationException

Storyboard_PropertyPathEmpty

Storyboard_PropertyPathEmpty

Error message

SR.Storyboard_PropertyPathEmpty

What it means

The timeline's PropertyPath resolved to an empty path: a TargetProperty was supplied (or derived) but its length is 0, so there is no property to animate. ClockTreeWalkRecursive rejects this with an InvalidOperationException because an empty path cannot map to an animatable property.

Solutions

  1. Supply a non-empty property path, e.g. Storyboard.TargetProperty="Opacity" or "(Panel.Background).(SolidColorBrush.Color)".
  2. In code, pass a PropertyPath with at least one segment.
  3. Validate any dynamically constructed property name for null/empty before beginning the storyboard.

Example fix

// before
string prop = GetPropertyFromConfig(); // ""
Storyboard.SetTargetProperty(anim, new PropertyPath(prop)); // throws

// after
string prop = GetPropertyFromConfig();
if (string.IsNullOrEmpty(prop)) prop = "Opacity"; // validate before use
Storyboard.SetTargetProperty(anim, new PropertyPath(prop));
Defensive patterns

Strategy: validation

Validate before calling

var pp = Storyboard.GetTargetProperty(anim);
if (pp == null || string.IsNullOrEmpty(pp.Path))
    throw new InvalidOperationException("Storyboard.TargetProperty path is empty");

Type guard

bool HasNonEmptyPath(Timeline t) => Storyboard.GetTargetProperty(t)?.Path is { Length: > 0 };

Try / catch

try { sb.Begin(fe); }
catch (InvalidOperationException ex) when (ex.Message.Contains("path")) {
    // fix: supply a non-empty PropertyPath
}

Prevention

When it happens

Trigger: Setting Storyboard.TargetProperty="" in XAML, or passing an empty/null path to Storyboard.SetTargetProperty in code (new PropertyPath("")).

Common situations: Binding TargetProperty from a resource/config value that is empty; dynamically built XAML where the property segment was dropped; refactoring that left an empty attribute in place.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs:463

                        throw new InvalidOperationException(SR.Format(SR.Storyboard_NoTarget, currentTimeline.GetType().ToString() ));
                    }
                }
            }

            // See if we have a property name to use.
            if( currentPropertyPath == null )
            {
                throw new InvalidOperationException(SR.Format(SR.Storyboard_TargetPropertyRequired, currentTimeline.GetType().ToString() ));
            }

            // A property name can be a straightforward property name (like "Angle")
            // but may be a more complex multi-step property path.  The two cases
            // are handled differently.
            using(currentPropertyPath.SetContext(targetObject))
            {
                if( currentPropertyPath.Length < 1 )
                {
                    throw new InvalidOperationException(SR.Storyboard_PropertyPathEmpty);
                }

                VerifyPathIsAnimatable(currentPropertyPath);

                if( currentPropertyPath.Length == 1 )
                {
                    // We have a simple single-step property.
                    targetProperty = currentPropertyPath.GetAccessor(0) as DependencyProperty;

                    if( targetProperty == null )
                    {
                        // Unfortunately it's not a DependencyProperty.
                        throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyProperty, currentPropertyPath.Path ));
                    }

                    VerifyAnimationIsValid(targetProperty, animationClock);

                    ObjectPropertyPair animatedTarget = new ObjectPropertyPair(targetObject, targetProperty);

View on GitHub (pinned to 81131a70a4)