{"record":{"id":"d1267014341e21fa","repo":"dotnet/wpf","slug":"storyboard-propertypathfrozencheckfailed","errorCode":"Storyboard_PropertyPathFrozenCheckFailed","errorMessage":"SR.Format(SR.Storyboard_PropertyPathFrozenCheckFailed, AccessorName(path, i-1), path.Path, intermediateFreezable.GetType().ToString())","messagePattern":"SR\\.Format\\(SR\\.Storyboard_PropertyPathFrozenCheckFailed, AccessorName\\(path, i-1\\), path\\.Path, intermediateFreezable\\.GetType\\(\\)\\.ToString\\(\\)\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs","lineNumber":724,"sourceCode":"            //  Object 0 is the Button, object 1 is the brush.\n            if( i == 1 )\n            {\n                intermediateFreezable = intermediateObject as Freezable;\n                if( intermediateFreezable != null && intermediateFreezable.IsFrozen )\n                {\n                    checkingFrozenState = false;\n                }\n            }\n            // Freezable objects (other than the one returned as the value of\n            //  the first property) must not be frozen if the first one isn't.\n            else if( checkingFrozenState )\n            {\n                intermediateFreezable = intermediateObject as Freezable;\n                if( intermediateFreezable != null && intermediateFreezable.IsFrozen )\n                {\n                    if( i > 0 )\n                    {\n                        throw new InvalidOperationException(SR.Format(SR.Storyboard_PropertyPathFrozenCheckFailed, AccessorName(path, i-1), path.Path, intermediateFreezable.GetType().ToString() ));\n                    }\n                    else\n                    {\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 )","sourceCodeStart":706,"sourceCodeEnd":742,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs#L706-L742","documentation":"An intermediate object along the animation property path is a frozen (immutable) Freezable, so Storyboard cannot traverse or modify through it. VerifyPathIsAnimatable throws this InvalidOperationException naming the accessor, path, and the frozen type.","triggerScenarios":"A path traverses a Freezable that was Freeze()d or auto-frozen (e.g. a frozen Brush or Geometry) and the animation needs to set a sub-property through it, with segment index i > 0.","commonSituations":"Animating (SolidColorBrush.Color) on a brush that was frozen for performance or declared in a resource dictionary that froze it; frozen Geometry/Transform collections in paths; freezing objects after cross-thread use then animating their sub-properties.","solutions":["Clone the frozen Freezable via CloneCurrentValue and target the unfrozen copy (e.g. assign a mutable brush to the element first).","Avoid calling Freeze() on objects whose sub-properties you animate.","Change the target to an unfrozen equivalent resource.","Assign a new live instance (element.Fill = new SolidColorBrush(...)) and animate that instead.","Restructure the path so it does not pass through the frozen object."],"exampleFix":"// before\nbrush.Freeze();\nelement.Fill = brush;\nstoryboard.Begin(element); // animates (SolidColorBrush.Color)\n// after\nvar animatableBrush = brush.CloneCurrentValue();\nelement.Fill = animatableBrush; // keep unfrozen\nstoryboard.Begin(element);","handlingStrategy":"validation","validationCode":"static bool PathObjectsUnfrozen(PropertyPath path, object root)\n{\n    path.Evaluate(root);\n    for (int i = 0; i < path.Get getItemCount; i++)\n    {\n        if (path.GetItem(i) is Freezable f && f.IsFrozen) return false;\n    }\n    return true;\n}","typeGuard":"bool IsAnimatableFreezable(object o) => !(o is Freezable f && f.IsFrozen);","tryCatchPattern":"try { storyboard.Begin(element); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"frozen\") || ex.Message.Contains(\"Frozen\"))\n{\n    // clone the frozen object and retry with mutable instance\n}","preventionTips":["Never Freeze objects whose sub-properties will be animated","CloneCurrentValue before animating shared resources","Keep animated brushes/geometries as live instances","Audit resource dictionaries for frozen resources used in animations"],"tags":["wpf","freezable","storyboard","propertypath"],"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"}