dotnet/wpf · error · ArgumentException

SR.Timing_ChildMustBeTimeline

Error message

SR.Timing_ChildMustBeTimeline

What it means

Thrown by TimelineGroup.AddChild (the IAddChild implementation for timeline parents like ParallelTimeline and Storyboard) when the child object added in XAML or code is not a Timeline. Only Timeline-derived children may be nested inside a timeline group.

Solutions

  1. Ensure the child is a Timeline-derived type (e.g. DoubleAnimation, DoubleAnimationUsingKeyFrames, ParallelTimeline)
  2. Fix XAML nesting so only animation/timeline elements are direct children of Storyboard/ParallelTimeline; wrap values in the correct animation element
  3. Cast or type-check the child before calling AddChild in code

Example fix

// before
storyboard.AddChild(someSetter);
// after
storyboard.AddChild(new DoubleAnimation(from, to, duration));
Defensive patterns

Strategy: validation

Validate before calling

if (child is Timeline timelineChild) storyboard.AddChild(timelineChild);

Type guard

bool isTimelineChild(object c) => c is Timeline;

Prevention

When it happens

Trigger: Calling AddChild (directly or via XAML object element under a Storyboard/ParallelTimeline) with an object that is not a Timeline, e.g. a string, a DoubleAnimation's keyframes misplaced, or a non-timeline element nested in a storyboard.

Common situations: XAML typos where a non-Timeline element is placed inside <Storyboard> or <ParallelTimeline> (e.g. <Setter>, a brush, or a typo'd tag that parses to the wrong type); programmatic AddChild calls with the wrong object.

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/dede1790bff3cdec. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/TimelineGroup.cs:145

        /// class implementation only if they determine that it's the right
        /// course of action.  The derived class can rely on Timeline's
        /// implementation of IAddChild.AddChild or implement their own
        /// following the Freezable pattern since that would be a public
        /// method.
        /// </remarks>
        /// <param name="child">An object representing the child that
        /// should be added.  If this is a Timeline it will be added to the
        /// Children collection; otherwise an exception will be thrown.</param>
        /// <exception cref="ArgumentException">The child parameter is not a
        /// Timeline.</exception>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected virtual void AddChild(object child)
        {
            Timeline timelineChild = child as Timeline;

            if (timelineChild == null)
            {
                throw new ArgumentException(SR.Timing_ChildMustBeTimeline, nameof(child));
            }
            else
            {
                Children.Add(timelineChild);
            }
        }

        /// <summary>
        /// Adds a text string as a child of this Timeline.
        /// </summary>
        /// <param name="childText">
        /// The text to add.
        /// </param>
        /// <remarks>
        /// A Timeline does not accept text as a child, so this method will
        /// raise an InvalididOperationException unless a derived class has
        /// overridden the behavior to add text.
        /// </remarks>

View on GitHub (pinned to 81131a70a4)