{"record":{"id":"b0fcd26d54f99d3e","repo":"dotnet/wpf","slug":"sr-mediacontext-infinitetickloop","errorCode":null,"errorMessage":"SR.MediaContext_InfiniteTickLoop","messagePattern":"SR\\.MediaContext_InfiniteTickLoop","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/MediaContext.cs","lineNumber":1792,"sourceCode":"            _isRendering = true;\n\n            // We don't need our promotion timers anymore.\n            _promoteRenderOpToInput.Stop();\n            _promoteRenderOpToRender.Stop();\n\n            bool gotException = true;\n\n            try\n            {\n                int tickLoopCount = 0;\n\n\n                do\n                {\n                    tickLoopCount++;\n                    if (tickLoopCount > 153)\n                    {\n                        throw new InvalidOperationException(SR.MediaContext_InfiniteTickLoop);\n                    }\n\n                    _timeManager.Tick();\n\n                    // Although the timing tree is now clean, during layout\n                    // more animations may be added, in which case we must tick\n                    // again to prevent \"first frame\" problems. If we do tick\n                    // again we want to do so at the same time as before, until\n                    // we are done. To that end, lock the tick time to the\n                    // first tick. Note that Lock/Unlock aren't counted, so we\n                    // can call Lock inside the loop and still safely call\n                    // Unlock just once after we are done.\n                    _timeManager.LockTickTime();\n\n                    // call all render callbacks\n                    FireInvokeOnRenderCallbacks();\n\n                    // signal that the frame has been updated and we are ready to render.","sourceCodeStart":1774,"sourceCodeEnd":1810,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/MediaContext.cs#L1774-L1810","documentation":"RenderMessageHandlerCore limits its animation tick loop to 153 iterations; if the time manager still needs ticking after that many passes (layout adding more animations each pass), it throws InvalidOperationException(SR.MediaContext_InfiniteTickLoop). This guards against an unbounded layout/animation feedback loop.","triggerScenarios":"A composition-target render pass in which each layout pass adds new animations or re-invalidates the timing tree, so the do/while loop keeps ticking forever — typically caused by animation that changes the layout of what drives it.","commonSituations":"SizeChanged / LayoutUpdated handlers starting new animations, animating a property whose change re-measures a container that re-triggers the animation, custom panels with feedback between measure and animated properties.","solutions":["Break the feedback loop: don't start/modify animations from LayoutUpdated or SizeChanged for the same element being animated.","Animate render transforms (TranslateTransform/ScaleTransform) instead of layout-affecting properties (Width, Margin).","Defer new animation starts via Dispatcher.BeginInvoke at Background priority so they apply after the tick loop ends.","Use Completed events rather than re-triggering on every layout pass."],"exampleFix":"// before\nprivate void OnLayoutUpdated(object s, EventArgs e) {\n    myAnim.BeginAnimation(WidthProperty, anim); // re-triggers layout -> loop\n}\n// after\nprivate void OnLoaded(object s, RoutedEventArgs e) {\n    var tt = new TranslateTransform();\n    el.RenderTransform = tt;\n    tt.BeginAnimation(TranslateTransform.XProperty, anim); // no layout change\n}","handlingStrategy":"validation","validationCode":"// Guard against re-entrant animation triggers:\nprivate bool _animating;\nvoid OnSizeChanged(object s, SizeChangedEventArgs e) {\n  if (_animating) return; // never restart the animation that causes the resize\n  _animating = true; StartAnimation();\n}","typeGuard":null,"tryCatchPattern":"try { RunAnimatedLayout(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"tick\")) { CancelAnimations(); Log(\"animation/layout feedback loop\"); }","preventionTips":["Never begin animations from LayoutUpdated/SizeChanged on the animated element","Animate RenderTransform properties instead of layout properties","Defer animation starts to background-priority dispatcher operations","Add re-entrancy flags around animation start code"],"tags":["wpf","animation","infinite-loop","layout"],"backgroundTag":"internal-invariant-violation","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"}