dotnet/wpf · error · InvalidOperationException
SR.IAnimatable_CantAnimateSealedDO
Error message
SR.IAnimatable_CantAnimateSealedDO
What it means
Thrown by IAnimatable.ApplyAnimationClock when the target object IsSealed. Sealed (frozen/immutable) Freezable/DependencyObject instances cannot be modified, including having animation clocks applied.
Solutions
- Call Clone() or CloneCurrentValue() on the frozen object and animate the unfrozen clone.
- Ensure the source object is not frozen before animating (check Freezable.IsFrozen).
- Animate a different unfrozen instance, e.g. animate the element property instead of the shared frozen resource.
Example fix
// before frozenBrush.ApplyAnimationClock(SolidColorBrush.ColorProperty, clock); // after var animatableBrush = frozenBrush.Clone(); animatableBrush.ApplyAnimationClock(SolidColorBrush.ColorProperty, clock);
Defensive patterns
Strategy: type-guard
Validate before calling
if (target is Freezable f && f.IsFrozen) target = f.Clone();
Type guard
static bool IsMutableForAnimation(DependencyObject o) => o is not Freezable f || !f.IsFrozen;
Try / catch
try { target.ApplyAnimationClock(dp, clock, handoff); } catch (InvalidOperationException ex) when (target is Freezable fz && fz.IsFrozen) { target = fz.Clone(); target.ApplyAnimationClock(dp, clock, handoff); } Prevention
- Check Freezable.IsFrozen before mutating or animating any Freezable.
- Keep separate frozen (shared, read-only) and unfrozen (animatable) instances.
- Delay Freeze() until after all animation setup is complete.
When it happens
Trigger: Calling ApplyAnimationClock on a frozen Freezable (e.g. a frozen Brush) or a sealed DependencyObject.
Common situations: Animating a Brush that was frozen via Freeze() for performance; sharing a frozen resource across elements and trying to animate it; animations targeting styles/resources marked frozen.
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
- IAnimatable_CantAnimateSealedDO
- SR.Format(SR.IAnimatable_CantAnimateSealedDO, dp…
- SR.Format(SR.Storyboard_ImmutableTargetNotSupported…
- SR.IAnimatable_CantAnimateSealedDO
- SR.IAnimatable_CantAnimateSealedDO (formatted with dp and…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/8dba297e340853fe.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/generators/IAnimatableHelper.cs:94
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)