dotnet/maui · error · ArgumentException

finishAt must be greater than beginAt

Error message

finishAt must be greater than beginAt

What it means

Thrown by Animation.Add after it has validated that beginAt and finishAt are each within [0,1]: the method additionally requires finishAt to be strictly greater than beginAt, because the child animation's duration is computed as finishAt - beginAt and a non-positive duration is meaningless.

Source

Thrown at src/Controls/src/Core/Animation.cs:54

			Func<double, double> transform = AnimationExtensions.Interpolate(start, end);
			Step = f => callback(transform(f));
		}
		/// <summary>
		/// Adds an <see cref="Animation"/> object to this <see cref="Animation"/> that begins at <paramref name="beginAt"/> and finishes at <paramref name="finishAt"/>.
		/// </summary>
		/// <param name="beginAt">The fraction into this animation at which the added child animation will begin animating.</param>
		/// <param name="finishAt">The fraction into this animation at which the added child animation will stop animating.</param>
		/// <param name="animation">The animation to add.</param>
		public void Add(double beginAt, double finishAt, Animation animation)
		{
			if (beginAt < 0 || beginAt > 1)
				throw new ArgumentOutOfRangeException(nameof(beginAt));

			if (finishAt < 0 || finishAt > 1)
				throw new ArgumentOutOfRangeException(nameof(finishAt));

			if (finishAt <= beginAt)
				throw new ArgumentException("finishAt must be greater than beginAt");

			animation.StartDelay = beginAt;
			animation.Duration = finishAt - beginAt;
			childrenAnimations.Add(animation);
		}

		/// <summary>
		/// Runs the <paramref name="owner" /> animation with the supplied parameters.
		/// </summary>
		/// <param name="owner">The owning animation that will be animated.</param>
		/// <param name="name">The name, or handle, that is used to access and track the animation and its state.</param>
		/// <param name="rate">The time, in milliseconds, between frames.</param>
		/// <param name="length">The number of milliseconds over which to interpolate the animation.</param>
		/// <param name="easing">The easing function to use to transition in, out, or in and out of the animation.</param>
		/// <param name="finished">An action to call when the animation is finished.</param>
		/// <param name="repeat">A function that should return true if the animation should continue.</param>
		public void Commit(IAnimatable owner, string name, uint rate = 16, uint length = 250, Easing easing = null, Action<double, bool> finished = null, Func<bool> repeat = null)
		{

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Ensure the arguments satisfy beginAt < finishAt (strictly), e.g. Add(0.2, 0.5, child).
  2. If the bounds come from variables, sort/validate them before calling Add: if (a >= b) (a, b) = (b, a).
  3. Skip the Add call entirely when finishAt <= beginAt if a zero-or-negative segment is legitimately unwanted.

Example fix

// before
parent.Add(0.5, 0.2, child);
// after
parent.Add(0.2, 0.5, child);
Defensive patterns

Strategy: validation

Validate before calling

static void AddSegment(Animation parent, double beginAt, double finishAt, Animation child)
{
    if (beginAt < 0 || beginAt > 1 || finishAt < 0 || finishAt > 1)
        throw new ArgumentOutOfRangeException();
    if (finishAt <= beginAt) (beginAt, finishAt) = (Math.Min(beginAt, finishAt), Math.Max(beginAt, finishAt));
    if (finishAt <= beginAt) return; // nothing to animate
    parent.Add(beginAt, finishAt, child);
}

Prevention

When it happens

Trigger: Calling animation.Add(beginAt, finishAt, child) where finishAt <= beginAt (including the equal case), after both values already passed the [0,1] range checks.

Common situations: Composing a staggered/sequential animation and swapping the two fractions; passing finishAt = beginAt expecting a zero-length segment; computing the bounds from variables whose order flipped at runtime.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/016ca3fc0148b5b1. Report an issue: GitHub.