dotnet/wpf · error · InvalidOperationException
SR.Format(SR.IAnimatable_CantAnimateSealedDO, dp…
Error message
SR.Format(SR.IAnimatable_CantAnimateSealedDO, dp, this.GetType())
What it means
Thrown by ContentElement.ApplyAnimationClock when the element IsSealed — i.e. the DependencyObject is sealed (typically because it belongs to a frozen or template-sealed state) and can no longer be animated. WPF throws InvalidOperationException with SR.IAnimatable_CantAnimateSealedDO naming the property and element type.
Solutions
- Check element.IsSealed before animating; skip or clone the element if sealed.
- Obtain a mutable copy (e.g. CloneCurrentValue or a new instance) instead of animating the sealed instance.
- Move animation code earlier in the element lifecycle, before sealing occurs (e.g. before the template is applied).
- Animate an ancestor or a wrapper element instead of the sealed object.
Example fix
// before
contentEl.ApplyAnimationClock(dp, clock, HandoffBehavior.Compose);
// after
if (!contentEl.IsSealed)
contentEl.ApplyAnimationClock(dp, clock, HandoffBehavior.Compose); Defensive patterns
Strategy: validation
Validate before calling
if (element.IsSealed)
throw new InvalidOperationException($"Cannot animate sealed element {element.GetType().Name}"); Type guard
bool CanAnimate(ContentElement e) => e != null && !e.IsSealed;
Try / catch
try { el.ApplyAnimationClock(dp, clock, behavior); }
catch (InvalidOperationException ex) when (el.IsSealed) { log.Warn($"Element {el.GetType().Name} is sealed; skipping animation"); } Prevention
- Check IsSealed before mutating any DependencyObject.
- Start animations early in the element lifecycle, before templates/styles seal it.
- Clone sealed elements (CloneCurrentValue) rather than animating them in place.
- Avoid animating shared or frozen resource instances.
When it happens
Trigger: Calling ApplyAnimationClock on a ContentElement whose IsSealed is true, e.g. an element already sealed by the framework (sealed styles/templates or frozen object state) — checked right before AnimationStorage.ApplyAnimationClock.
Common situations: Attempting to animate elements inside a sealed template or after the object was sealed; animating shared/frozen resources; applying animations during shutdown or after the element was locked by its container.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Animation_Invalid_DefaultValue
- CannotChangeAfterSealed
- CannotChangeAfterSealed
- SR.Animation_Invalid_DefaultValue
- SR.Animation_NoTextChildren
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/21bc94f1ce9a9009.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Generated/ContentElement.cs:87
if (!AnimationStorage.IsPropertyAnimatable(this, dp))
{
throw new ArgumentException(SR.Format(SR.Animation_DependencyPropertyIsNotAnimatable, dp.Name, this.GetType()), nameof(dp));
}
if (clock != null
&& !AnimationStorage.IsAnimationValid(dp, clock.Timeline))
{
throw new ArgumentException(SR.Format(SR.Animation_AnimationTimelineTypeMismatch, clock.Timeline.GetType(), dp.Name, dp.PropertyType), nameof(clock));
}
if (!HandoffBehaviorEnum.IsDefined(handoffBehavior))
{
throw new ArgumentException(SR.Animation_UnrecognizedHandoffBehavior);
}
if (IsSealed)
{
throw new InvalidOperationException(SR.Format(SR.IAnimatable_CantAnimateSealedDO, dp, this.GetType()));
}
AnimationStorage.ApplyAnimationClock(this, dp, clock, handoffBehavior);
}
/// <summary>
/// Starts an animation for a DependencyProperty. The animation will
/// begin when the next frame is rendered.
/// </summary>
/// <param name="dp">
/// The DependencyProperty to animate.
/// </param>
/// <param name="animation">
/// <para>The AnimationTimeline to used to animate the property.</para>
/// <para>If the AnimationTimeline's BeginTime is null, any current animations
/// will be removed and the current value of the property will be held.</para>
/// <para>If this value is null, all animations will be removed from the property
/// and the property value will revert back to its base value.</para>View on GitHub (pinned to 81131a70a4)