dotnet/wpf · error · InvalidOperationException

SR.Timing_AccelAndDecelGreaterThanOne

Error message

SR.Timing_AccelAndDecelGreaterThanOne

What it means

Timeline.ValidateTimeline (invoked when the timeline is frozen via FreezeCore) enforces the invariant AccelerationRatio + DecelerationRatio <= 1; exceeding it throws InvalidOperationException with Timing_AccelAndDecelGreaterThanOne. The timing engine cannot both accelerate and decelerate for more than 100% of the duration, so the freeze fails.

Solutions

  1. Ensure AccelerationRatio + DecelerationRatio <= 1 before freezing; scale both down proportionally if needed.
  2. Freeze manually at a point you control so you get the error early with a clear stack.
  3. If ratios come from config, validate the pair together, not individually.

Example fix

// before
anim.AccelerationRatio = 0.7;
anim.DecelerationRatio = 0.5; // sum 1.2
// after
double a = 0.7, d = 0.5;
double scale = a + d > 1.0 ? 1.0 / (a + d) : 1.0;
anim.AccelerationRatio = a * scale;
anim.DecelerationRatio = d * scale;
Defensive patterns

Strategy: validation

Validate before calling

if (a + d > 1.0) { double s = 1.0 / (a + d); a *= s; d *= s; }
anim.AccelerationRatio = a; anim.DecelerationRatio = d;
anim.Freeze();

Type guard

static bool AreValidRatios(double a, double d) => a >= 0 && a <= 1 && d >= 0 && d <= 1 && a + d <= 1;

Try / catch

try { anim.Freeze(); }
catch (InvalidOperationException) { /* rescale ratios and refreeze */ }

Prevention

When it happens

Trigger: Setting AccelerationRatio = 0.7 and DecelerationRatio = 0.5 (sum 1.2) and then calling timeline.Freeze() — or implicitly when WPF freezes the timeline (e.g., assigning it to a style/resource used from multiple threads). Individually valid values can still sum > 1.

Common situations: Tuning both ratios independently in XAML where each stays <= 1 but the sum exceeds 1; copying ratios from two different animations; animation templates whose combined defaults sum above 1.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/Timeline.cs:720

        }

        /// <summary>
        /// This method will throw an exception if a timeline has been incorrectly
        /// constructed.  Currently we validate all possible values when they are 
        /// set, but it is not possible to do this for Acceleration/DecelerationRatio.
        /// 
        /// The reason is when a timeline is instantiated in xaml the properties are
        /// set with direct calls to DependencyObject.SetValue.  This means our only
        /// chance to validate the value is in the ValidateValue callback, which does
        /// not allow querying of other DPs.  Acceleration/DecelerationRatio are invalid
        /// if their sum is > 1.  This can't be verified in the ValidateValue callback,
        /// so is done here.
        /// </summary>
        private void ValidateTimeline()
        {
            if (AccelerationRatio + DecelerationRatio > 1)
            {
                throw new InvalidOperationException(SR.Timing_AccelAndDecelGreaterThanOne);
            }
        }

        #endregion // Methods

        #region Events

        /// <summary>
        /// Raised whenever the value of the CurrentStateInvalidated property changes.
        /// </summary>
        public event EventHandler CurrentStateInvalidated
        {
            add
            {
                AddEventHandler(CurrentStateInvalidatedKey, value);
            }
            remove
            {

View on GitHub (pinned to 81131a70a4)