{"record":{"id":"f436e78c844f49eb","repo":"dotnet/wpf","slug":"storyboard-propertypathmustpointtodependencyobject","errorCode":"Storyboard_PropertyPathMustPointToDependencyObject","errorMessage":"SR.Format(SR.Storyboard_PropertyPathMustPointToDependencyObject, AccessorName(path, i-1), path.Path)","messagePattern":"SR\\.Format\\(SR\\.Storyboard_PropertyPathMustPointToDependencyObject, AccessorName\\(path, i-1\\), path\\.Path\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs","lineNumber":745,"sourceCode":"                    {\n                        // i == 0 means the targeted object itself is a frozen Freezable.\n                        //  This need a different error message.\n                        throw new InvalidOperationException(SR.Format(SR.Storyboard_ImmutableTargetNotSupported, path.Path));\n                    }\n                }\n            }\n\n            // The last object + property pairing (the one we're actually going\n            //  to stick the clock on) has further requirements.\n            if( i == path.Length-1 )\n            {\n                DependencyObject intermediateDO = intermediateObject as DependencyObject;\n                DependencyProperty intermediateDP = intermediateProperty as DependencyProperty;\n\n                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        }","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs#L727-L763","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnew PropertyPath(\"MyPoco.Name.Length\"); // MyPoco is a plain CLR object\n// after\nnew PropertyPath(\"(UIElement.Opacity)\"); // DO + DP chain","handlingStrategy":"validation","validationCode":"static bool PathIntermediatesAreDO(object root, PropertyPath path)\n{\n    try {\n        path.Evaluate(root);\n        for (int i = 0; i < path.Get getItemCount; i++)\n            if (!(path.GetItem(i) is DependencyObject) && i > 0) return false;\n        return true;\n    } catch { return false; }\n}","typeGuard":"bool IsDependencyObject(object o) => o is DependencyObject;","tryCatchPattern":"try { storyboard.Begin(target); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"DependencyObject\"))\n{\n    // restructure the path through DO/DP objects only\n}","preventionTips":["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"],"tags":["wpf","propertypath","dependencyobject","storyboard"],"backgroundTag":"type-mismatch","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"}