{"record":{"id":"016ca3fc0148b5b1","repo":"dotnet/maui","slug":"finishat-must-be-greater-than-beginat","errorCode":null,"errorMessage":"finishAt must be greater than beginAt","messagePattern":"finishAt must be greater than beginAt","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Controls/src/Core/Animation.cs","lineNumber":54,"sourceCode":"\t\t\tFunc<double, double> transform = AnimationExtensions.Interpolate(start, end);\n\t\t\tStep = f => callback(transform(f));\n\t\t}\n\t\t/// <summary>\n\t\t/// Adds an <see cref=\"Animation\"/> object to this <see cref=\"Animation\"/> that begins at <paramref name=\"beginAt\"/> and finishes at <paramref name=\"finishAt\"/>.\n\t\t/// </summary>\n\t\t/// <param name=\"beginAt\">The fraction into this animation at which the added child animation will begin animating.</param>\n\t\t/// <param name=\"finishAt\">The fraction into this animation at which the added child animation will stop animating.</param>\n\t\t/// <param name=\"animation\">The animation to add.</param>\n\t\tpublic void Add(double beginAt, double finishAt, Animation animation)\n\t\t{\n\t\t\tif (beginAt < 0 || beginAt > 1)\n\t\t\t\tthrow new ArgumentOutOfRangeException(nameof(beginAt));\n\n\t\t\tif (finishAt < 0 || finishAt > 1)\n\t\t\t\tthrow new ArgumentOutOfRangeException(nameof(finishAt));\n\n\t\t\tif (finishAt <= beginAt)\n\t\t\t\tthrow new ArgumentException(\"finishAt must be greater than beginAt\");\n\n\t\t\tanimation.StartDelay = beginAt;\n\t\t\tanimation.Duration = finishAt - beginAt;\n\t\t\tchildrenAnimations.Add(animation);\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Runs the <paramref name=\"owner\" /> animation with the supplied parameters.\n\t\t/// </summary>\n\t\t/// <param name=\"owner\">The owning animation that will be animated.</param>\n\t\t/// <param name=\"name\">The name, or handle, that is used to access and track the animation and its state.</param>\n\t\t/// <param name=\"rate\">The time, in milliseconds, between frames.</param>\n\t\t/// <param name=\"length\">The number of milliseconds over which to interpolate the animation.</param>\n\t\t/// <param name=\"easing\">The easing function to use to transition in, out, or in and out of the animation.</param>\n\t\t/// <param name=\"finished\">An action to call when the animation is finished.</param>\n\t\t/// <param name=\"repeat\">A function that should return true if the animation should continue.</param>\n\t\tpublic void Commit(IAnimatable owner, string name, uint rate = 16, uint length = 250, Easing easing = null, Action<double, bool> finished = null, Func<bool> repeat = null)\n\t\t{","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Controls/src/Core/Animation.cs#L36-L72","documentation":"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.","triggerScenarios":"Calling animation.Add(beginAt, finishAt, child) where finishAt <= beginAt (including the equal case), after both values already passed the [0,1] range checks.","commonSituations":"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.","solutions":["Ensure the arguments satisfy beginAt < finishAt (strictly), e.g. Add(0.2, 0.5, child).","If the bounds come from variables, sort/validate them before calling Add: if (a >= b) (a, b) = (b, a).","Skip the Add call entirely when finishAt <= beginAt if a zero-or-negative segment is legitimately unwanted."],"exampleFix":"// before\nparent.Add(0.5, 0.2, child);\n// after\nparent.Add(0.2, 0.5, child);","handlingStrategy":"validation","validationCode":"static void AddSegment(Animation parent, double beginAt, double finishAt, Animation child)\n{\n    if (beginAt < 0 || beginAt > 1 || finishAt < 0 || finishAt > 1)\n        throw new ArgumentOutOfRangeException();\n    if (finishAt <= beginAt) (beginAt, finishAt) = (Math.Min(beginAt, finishAt), Math.Max(beginAt, finishAt));\n    if (finishAt <= beginAt) return; // nothing to animate\n    parent.Add(beginAt, finishAt, child);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass beginAt < finishAt in [0,1] when composing child animations.","When bounds come from variables, sort them before calling Add.","Add a unit test that calls Add with equal and reversed bounds to catch regressions."],"tags":["animation","argument-validation","timing"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}