{"record":{"id":"a5abfedb5dd76183","repo":"dotnet/wpf","slug":"storyboard-propertypathincludesnonanimatableproperty","errorCode":"Storyboard_PropertyPathIncludesNonAnimatableProperty","errorMessage":"SR.Format(SR.Storyboard_PropertyPathIncludesNonAnimatableProperty, path.Path, intermediateDP.Name)","messagePattern":"SR\\.Format\\(SR\\.Storyboard_PropertyPathIncludesNonAnimatableProperty, path\\.Path, intermediateDP\\.Name\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs","lineNumber":760,"sourceCode":"                if( intermediateDO == null )\n                {\n                    Debug.Assert( i > 0, \"The caller should not have set the PropertyPath context to a non DependencyObject.\" );\n                    throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyObject, AccessorName(path, i-1), path.Path));\n                }\n\n                if( intermediateDP == null )\n                {\n                    throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyProperty, path.Path ));\n                }\n\n                if( checkingFrozenState && intermediateDO.IsSealed )\n                {\n                    throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathSealedCheckFailed, intermediateDP.Name, path.Path, intermediateDO));\n                }\n\n                if(!AnimationStorage.IsPropertyAnimatable(intermediateDO, intermediateDP) )\n                {\n                    throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathIncludesNonAnimatableProperty, path.Path, intermediateDP.Name));\n                }\n            }\n        }\n    }\n\n    private static string AccessorName( PropertyPath path, int index )\n    {\n        object propertyAccessor = path.GetAccessor(index);\n\n        if( propertyAccessor is DependencyProperty )\n        {\n            return ((DependencyProperty)propertyAccessor).Name;\n        }\n        else if( propertyAccessor is PropertyInfo )\n        {\n            return ((PropertyInfo)propertyAccessor).Name;\n        }\n        else if( propertyAccessor is PropertyDescriptor )","sourceCodeStart":742,"sourceCodeEnd":778,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs#L742-L778","documentation":"Every property along the animation property path must be animatable — AnimationStorage.IsPropertyAnimatable must accept it. VerifyPathIsAnimatable throws this InvalidOperationException when an intermediate or final DependencyProperty (named in the message) cannot host an AnimationClock (e.g. read-only or wrong value type).","triggerScenarios":"Storybard.TargetProperty references a DependencyProperty that is not animatable — read-only DPs, DPs whose type has no matching AnimationTimeline, or non-animatable metadata (CannotBeAnimated).","commonSituations":"Animating read-only properties like ActualWidth; animating a DP whose PropertyType has no corresponding animation type (e.g. animating a complex object DP with a DoubleAnimation); animating properties on custom DPs registered without animatable types.","solutions":["Change the path property to an animatable one (e.g. Width instead of ActualWidth).","Match the AnimationTimeline type to the DP's PropertyType (DoubleAnimation for double DPs, ColorAnimation for Color, etc.).","For read-only DPs, animate the property that drives them instead.","For custom DPs, ensure the type has a corresponding AnimationTimeline and the property is animatable.","Wrap the value in an animatable DP and animate that."],"exampleFix":"// before\nnew PropertyPath(\"(FrameworkElement.ActualWidth)\"); // read-only, not animatable\n// after\nnew PropertyPath(\"(FrameworkElement.Width)\");","handlingStrategy":"validation","validationCode":"bool CheckAnimatable(DependencyObject d, DependencyProperty p) =>\n    AnimationStorage.IsPropertyAnimatable(d, p); // or reflect: !p.ReadOnly && p.GetMetadata(d.GetType()).TypeKey != null","typeGuard":"bool IsAnimatableProperty(DependencyObject d, DependencyProperty p) =>\n    !p.ReadOnly && AnimationStorage.IsPropertyAnimatable(d, p);","tryCatchPattern":"try { storyboard.Begin(target); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not animatable\"))\n{\n    // substitute an animatable property for the one named in the message\n}","preventionTips":["Never animate read-only properties (ActualWidth, ActualHeight)","Match animation class to the DP's PropertyType","Consult animatable properties list in WPF docs per control","For custom DPs, verify a matching AnimationTimeline exists"],"tags":["wpf","animation","propertypath","dependencyproperty"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}