{"record":{"id":"9a25baac566926a0","repo":"stride3d/stride","slug":"this-animationclip-is-frozen","errorCode":null,"errorMessage":"This AnimationClip is frozen","messagePattern":"This AnimationClip is frozen","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Engine/Animations/AnimationClip.cs","lineNumber":68,"sourceCode":"        public List<AnimationCurve> Curves = new List<AnimationCurve>();\n\n        public AnimationData[] OptimizedAnimationDatas;\n\n        /// <summary>\n        /// Set this flag to true when the channel information of the clip have changed and need to be rescan by engine.\n        /// </summary>\n        [DataMemberIgnore]\n        public bool ShouldRescanChannels;\n\n        /// <summary>\n        /// Adds a named curve.\n        /// </summary>\n        /// <param name=\"propertyName\">Name of the property.</param>\n        /// <param name=\"curve\">The curve.</param>\n        public void AddCurve(string propertyName, AnimationCurve curve, bool isUserCustomProperty = false)\n        {\n            if (Frozen)\n                throw new InvalidOperationException(\"This AnimationClip is frozen\");\n\n            // Add channel\n            Channels.Add(propertyName, new Channel\n            {\n                PropertyName = propertyName,\n                CurveIndex = Curves.Count,\n                ElementType = curve.ElementType,\n                ElementSize = curve.ElementSize,\n                IsUserCustomProperty = isUserCustomProperty,\n            });\n            Curves.Add(curve);\n        }\n\n        public AnimationCurve GetCurve(string propertyName)\n        {\n            Channel channel;\n            if (!Channels.TryGetValue(propertyName, out channel))\n                return null;","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Engine/Animations/AnimationClip.cs#L50-L86","documentation":"AnimationClip.Frozen marks a clip as immutable (typically after baking/optimization for runtime use). AddCurve checks Frozen first and throws this InvalidOperationException rather than mutating a frozen clip, since adding channels after freezing would invalidate precomputed curve data.","triggerScenarios":"Calling clip.AddCurve(propertyName, curve) on a clip whose Frozen property is true — e.g. modifying a clip after it was frozen by the animation system or by explicitly setting Frozen, at AnimationClip.cs:68.","commonSituations":"Procedurally extending an animation clip at runtime after it has been optimized/frozen; editing a clip asset already loaded and frozen by the engine; game code reusing a shared frozen clip to add per-entity curves.","solutions":["Add all curves before freezing the clip (set Frozen only after clip construction is complete).","Create a new unfrozen AnimationClip, copy the curves into it, add the new curve, and use that clip instead.","If you own the lifecycle and know the clip isn't in use, temporarily set Frozen = false, add the curve, then re-freeze.","Check callers like Start/SubtractAnimations/ExportAnimation that operate on already-frozen clips and clone first."],"exampleFix":"// before\nmyClip.AddCurve(\"Base[Node].Scale\", curve); // throws: clip is frozen\n\n// after\nif (!myClip.Frozen)\n    myClip.AddCurve(\"Base[Node].Scale\", curve);\nelse {\n    var newClip = new AnimationClip();\n    // copy channels from myClip, then:\n    newClip.AddCurve(\"Base[Node].Scale\", curve);\n}","handlingStrategy":"validation","validationCode":"// Check before mutating\nif (clip.Frozen)\n    throw new InvalidOperationException(\"Cannot AddCurve on a frozen AnimationClip; create a copy first\");\nclip.AddCurve(propertyName, curve);","typeGuard":null,"tryCatchPattern":"try { clip.AddCurve(name, curve); }\ncatch (InvalidOperationException ex) when (ex.Message == \"This AnimationClip is frozen\") { /* clone clip, add curve to the clone */ }","preventionTips":["Freeze clips only after all curves are added","Treat frozen clips as read-only and copy before extending","Centralize clip mutation behind a helper that checks Frozen"],"tags":["animation","immutable","frozen","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}