dotnet/wpf · error · InvalidOperationException
Storyboard_PropertyPathMustPointToDependencyObject
Storyboard_PropertyPathMustPointToDependencyObject
Error message
SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyObject, AccessorName(path, i-1), path.Path)
What it means
Every intermediate object in an animation property path must be a DependencyObject so WPF can attach clocks to its properties. VerifyPathIsAnimatable throws this InvalidOperationException when a path segment (i > 0) resolves to a plain CLR object instead.
Solutions
- Make every intermediate step a DependencyObject; animate only DependencyObject.(DependencyProperty) chains.
- Change intermediate properties on your classes to DependencyProperties on DependencyObject-derived types.
- Trim the path so it ends at the DependencyProperty instead of continuing into a CLR object.
- Use attached-property syntax to route through known DOs.
- Inspect the reported accessor and replace that segment with a DO-based path.
Example fix
// before
new PropertyPath("MyPoco.Name.Length"); // MyPoco is a plain CLR object
// after
new PropertyPath("(UIElement.Opacity)"); // DO + DP chain Defensive patterns
Strategy: validation
Validate before calling
static bool PathIntermediatesAreDO(object root, PropertyPath path)
{
try {
path.Evaluate(root);
for (int i = 0; i < path.Get getItemCount; i++)
if (!(path.GetItem(i) is DependencyObject) && i > 0) return false;
return true;
} catch { return false; }
} Type guard
bool IsDependencyObject(object o) => o is DependencyObject;
Try / catch
try { storyboard.Begin(target); }
catch (InvalidOperationException ex) when (ex.Message.Contains("DependencyObject"))
{
// restructure the path through DO/DP objects only
} Prevention
- Build property paths only through DependencyObject/DependencyProperty chains
- Convert wrapped CLR objects to DO/DP when animation is needed
- End paths at the DependencyProperty; don't over-path
- Test paths against sample object graphs before shipping
When it happens
Trigger: A Storyboard.TargetProperty path walks through a non-DependencyObject — e.g. an intermediate property returns a plain POCO, struct, or string, and the path tries to descend further into it.
Common situations: Pathing through non-DP CLR wrappers; animating through Point/Size structs treated as intermediates; path segments through collections of plain objects; mis-ordered path where the animatable property segment is followed by extra segments.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Storyboard_PropertyPathEmpty
- Storyboard_PropertyPathFrozenCheckFailed
- Storyboard_PropertyPathMustPointToDependencyProperty
- Storyboard_PropertyPathObjectNotFound
- Storyboard_PropertyPathPropertyNotFound
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/f436e78c844f49eb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs:745
{
// i == 0 means the targeted object itself is a frozen Freezable.
// This need a different error message.
throw new InvalidOperationException(SR.Format(SR.Storyboard_ImmutableTargetNotSupported, path.Path));
}
}
}
// The last object + property pairing (the one we're actually going
// to stick the clock on) has further requirements.
if( i == path.Length-1 )
{
DependencyObject intermediateDO = intermediateObject as DependencyObject;
DependencyProperty intermediateDP = intermediateProperty as DependencyProperty;
if( intermediateDO == null )
{
Debug.Assert( i > 0, "The caller should not have set the PropertyPath context to a non DependencyObject." );
throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyObject, AccessorName(path, i-1), path.Path));
}
if( intermediateDP == null )
{
throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyProperty, path.Path ));
}
if( checkingFrozenState && intermediateDO.IsSealed )
{
throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathSealedCheckFailed, intermediateDP.Name, path.Path, intermediateDO));
}
if(!AnimationStorage.IsPropertyAnimatable(intermediateDO, intermediateDP) )
{
throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathIncludesNonAnimatableProperty, path.Path, intermediateDP.Name));
}
}
}View on GitHub (pinned to 81131a70a4)