{"record":{"id":"1bdf24b1b5179702","repo":"dotnet/wpf","slug":"sr-format-sr-storyboard-immutabletargetnotsupported-path","errorCode":null,"errorMessage":"SR.Format(SR.Storyboard_ImmutableTargetNotSupported, path.Path)","messagePattern":"SR\\.Format\\(SR\\.Storyboard_ImmutableTargetNotSupported, path\\.Path\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs","lineNumber":874,"sourceCode":"\n            // We need to clone the value of the target, and from here onwards\n            //  try to pretend that it is the actual value.\n            Debug.Assert(targetPropertyValue is Freezable, \"We shouldn't be trying to clone a type we don't understand.  PropertyCloningRequired() has improperly flagged the current value as 'need to clone'.\");\n\n            // To enable animations on frozen Freezable objects, complex\n            //  path processing is done on a clone of the value.\n            Freezable clone = ((Freezable)targetPropertyValue).Clone();\n            SetComplexPathClone( targetObject, targetProperty, targetPropertyValue, clone );\n\n            // Promote the clone to the EffectiveValues cache\n            targetObject.InvalidateProperty(targetProperty);\n\n            // We're supposed to have the animatable clone in place by now.  But if\n            //  things went sour for whatever reason, halt the app instead of corrupting\n            //  the frozen object.\n            if( targetObject.GetValue(targetProperty) != clone )\n            {\n                throw new InvalidOperationException(SR.Format(SR.Storyboard_ImmutableTargetNotSupported, path.Path));\n            }\n\n            // Now that we have a clone, update the animatedObject and animatedProperty\n            //  with references to those on the clone.\n            using(path.SetContext(targetObject))\n            {\n                animatedObject = path.LastItem as DependencyObject;\n                animatedProperty = path.LastAccessor as DependencyProperty;\n            }\n\n            // And set up to listen to changes on this clone.\n            ChangeListener.ListenToChangesOnFreezable(\n                targetObject, clone, targetProperty, (Freezable)targetPropertyValue );\n        }\n\n        // Apply animation clock on the animated object/animated property.\n        ObjectPropertyPair directApplyTarget = new ObjectPropertyPair( animatedObject, animatedProperty );\n        UpdateMappings( clockMappings, directApplyTarget, animationClock );","sourceCodeStart":856,"sourceCodeEnd":892,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs#L856-L892","documentation":"Thrown by ProcessComplexPath when a complex path resolved to a frozen (immutable) Freezable target and the library's clone-in-place strategy failed. WPF animates frozen Freezables by substituting a mutable clone into the tree; if the target property's value is not the clone after processing, the app is halted rather than corrupting the frozen object.","triggerScenarios":"Storyboard with a complex PropertyPath that walks into a Freezable that is frozen (e.g. a Brush inside a frozen resource) and GetComplexPathValue cannot install a cloned, animatable instance at the expected property.","commonSituations":"Animating properties of shared resources defined with PresentationOptions:Freeze='True' or retrieved from a frozen cache; cross-thread shared brushes; deep property paths like 'Fill.(SolidColorBrush.Opacity)' on a frozen brush.","solutions":["Do not freeze the Freezable being animated: remove PresentationOptions:Freeze or call GetAsFrozen less aggressively so the animation can target it.","Create an unfrozen copy of the resource specifically for animation and target that instance.","Simplify the property path so it targets a mutable DependencyObject property rather than traversing into frozen sub-objects.","If the freeze is mandatory, animate a different mechanism (e.g. bind to a computed value or use a CompositionTarget.Rendering loop)."],"exampleFix":"// before\n<SolidColorBrush x:Key=\"animBrush\" Color=\"Red\" PresentationOptions:Freeze=\"True\" />\n// after\n<SolidColorBrush x:Key=\"animBrush\" Color=\"Red\" /> <!-- leave unfrozen so it can be cloned/animated -->","handlingStrategy":"validation","validationCode":"var val = targetObject.GetValue(targetProperty) as Freezable;\nif (val != null && val.IsFrozen)\n{\n    var clone = val.CloneCurrentValue(); // animatable copy\n}","typeGuard":"bool CanAnimate(object o) => o is Freezable f ? !f.IsFrozen : o is DependencyObject;","tryCatchPattern":"try { storyboard.Begin(target, true); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"immutable\")) { /* use an unfrozen clone as the animation source */ }","preventionTips":["Don't freeze Freezables you intend to animate","Remove PresentationOptions:Freeze=\"True\" on animated resources","Clone frozen resources before targeting them in a storyboard"],"tags":["wpf","animation","freezable","frozen","invalid-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}