dotnet/wpf · error · InvalidOperationException

SR.Format(SR.Storyboard_AnimationMismatch…

Error message

SR.Format(SR.Storyboard_AnimationMismatch, animationClock.Timeline.GetType(), targetProperty.Name, targetProperty.PropertyType)

What it means

The AnimationClock being applied must match the target DependencyProperty's value type — IsAnimationClockValid rejects clocks whose Timeline produces an incompatible type. VerifyAnimationIsValid throws this InvalidOperationException naming the clock's Timeline type, the property, and its expected PropertyType.

Solutions

  1. Use an AnimationTimeline matching the property type: DoubleAnimation for double, ColorAnimation for Color, ThicknessAnimation for Thickness, PointAnimation for Point, etc.
  2. Use ObjectAnimationUsingKeyFrames for non-standard types.
  3. Update the child timeline type inside the storyboard for the named target property.
  4. Check the exception's propertyType field and pick the matching animation class.
  5. Split the storyboard so each property gets a correctly-typed animation.

Example fix

// before
<ColorAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:1" />
<!-- after -->
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:1" />
Defensive patterns

Strategy: validation

Validate before calling

static bool AnimationMatchesProperty(DependencyProperty dp, AnimationClock clock)
{
    var animType = clock.Timeline.GetType();
    return dp.PropertyType == typeof(double) && animType.Name.StartsWith("Double")
        || dp.PropertyType == typeof(Color) && animType.Name.StartsWith("Color")
        || dp.PropertyType == typeof(Thickness) && animType.Name.StartsWith("Thickness")
        || dp.PropertyType == typeof(Point) && animType.Name.StartsWith("Point");
}

Type guard

bool IsMatchingAnimation(DependencyProperty dp, Timeline t) =>
    t.GetType().Name.StartsWith(dp.PropertyType.Name) || t is ObjectAnimationUsingKeyFrames;

Try / catch

try { storyboard.Begin(target, true); }
catch (InvalidOperationException ex) when (ex.Message.Contains("animation"))
{
    // inspect ex.Message for propertyType and swap the child timeline type
}

Prevention

When it happens

Trigger: Applying a Storyboard whose child AnimationTimeline type does not fit the target property — e.g. a DoubleAnimation targeting a Color property, or a ColorAnimation targeting a double/Thickness property, via Begin, Apply, or HandoffBehavior composition.

Common situations: Copy-pasting storyboards between properties of different types; Animatable sub-objects (GradientStop.Color vs element.Opacity) swapped; refactors changing property types; animations from shared resource dictionaries applied to mismatched targets.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/d6f6dca37a9837e1. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs:796

        else if( propertyAccessor is PropertyDescriptor )
        {
            return ((PropertyDescriptor)propertyAccessor).Name;
        }
        else
        {
            return "[Unknown]";
        }
    }

    /// <summary>
    ///     Makes sure that the given clock can animate the given property -
    /// throw an exception otherwise.
    /// </summary>
    private static void VerifyAnimationIsValid( DependencyProperty targetProperty, AnimationClock animationClock )
    {
        if( !AnimationStorage.IsAnimationClockValid(targetProperty, animationClock) )
        {
            throw new InvalidOperationException(SR.Format(SR.Storyboard_AnimationMismatch, animationClock.Timeline.GetType(), targetProperty.Name, targetProperty.PropertyType));
        }
    }

    /// <summary>
    ///     For complex property paths, we need to dig our way down to the
    /// property and attach the animation clock there.  We will not be able to
    /// actually attach the clocks if the targetProperty points to a frozen
    /// Freezable.  More extensive handling will be required for that case.
    /// </summary>
    private void ProcessComplexPath( HybridDictionary clockMappings, DependencyObject targetObject,
        PropertyPath path, AnimationClock animationClock, HandoffBehavior handoffBehavior, Int64 layer )
    {
        Debug.Assert(path.Length > 1, "This method shouldn't even be called for a simple property path.");

        // For complex paths, the target object/property differs from the actual
        //  animated object/property.
        //
        // Example:

View on GitHub (pinned to 81131a70a4)