AvaloniaUI/Avalonia · error · InvalidOperationException

SpeedRatio value cannot be negative.

Error message

SpeedRatio value cannot be negative.

What it means

Thrown by AnimationInstance.FetchProperties when Animation.SpeedRatio is negative. SpeedRatio scales playback rate; a negative value would imply reverse playback at the rate level, which the timing engine does not support, so it is rejected during the property fetch that runs on each sync.

Source

Thrown at src/Avalonia.Base/Animation/AnimationInstance`1.cs:89

            _interpolator = Interpolator;
            _baseClock = baseClock;
            _initialKFValue = default!;
            _neutralValue = default!;
            _shouldPauseOnInvisible = shouldPauseOnInvisible;
            _isFirstFrame = true;
            _isInFirstInitialDelay = true;
            _speedRatio = 1;
            FetchProperties();
        }

        private void FetchProperties()
        {
            _easeFunc = _animation.Easing;

            _speedRatioPrev = _speedRatio;
            _speedRatio = _animation.SpeedRatio;
            if (_speedRatio < 0d)
                throw new InvalidOperationException("SpeedRatio value cannot be negative.");

            _initialDelay = _animation.Delay;
            if (_initialDelay < TimeSpan.Zero)
                throw new InvalidOperationException("Delay value cannot be negative.");

            _duration = _animation.Duration;
            if (_duration < TimeSpan.Zero)
                throw new InvalidOperationException("Duration value cannot be negative.");

            _iterationDelay = _animation.DelayBetweenIterations;
            if (_iterationDelay < TimeSpan.Zero)
                throw new InvalidOperationException("DelayBetweenIterations value cannot be negative.");

            if (_animation.IterationCount.RepeatType == IterationType.Many)
            {
                if (_animation.IterationCount.Value > long.MaxValue)
                    throw new InvalidOperationException("IterationCount value cannot be larger than long.MaxValue.");
                _iterationCount = (long)_animation.IterationCount.Value;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Clamp SpeedRatio to >= 0 before assigning: anim.SpeedRatio = Math.Max(0, value).
  2. If reverse playback is desired, use IterationCount / Direction semantics or reverse the keyframe order rather than a negative ratio.
  3. Validate the bound source value (e.g. slider Minimum=0) so SpeedRatio cannot become negative.
  4. Review XAML for stray negative literals on SpeedRatio.

Example fix

// before
<Animation SpeedRatio="-1" Duration="0:0:1"/>

// after
<Animation SpeedRatio="1" Duration="0:0:1"/>
Defensive patterns

Strategy: validation

Validate before calling

// clamp SpeedRatio to a non-negative value
animation.SpeedRatio = Math.Max(0d, computedSpeedRatio);

Type guard

static bool IsValidSpeedRatio(double v) => v >= 0d;

Prevention

When it happens

Trigger: Setting Animation.SpeedRatio to a value < 0 (e.g. via XAML SpeedRatio="-1" or binding SpeedRatio to a computed negative number). FetchProperties reads _animation.SpeedRatio on each fetch and throws immediately when it is negative.

Common situations: Binding SpeedRatio to a data source that can go negative (e.g. a slider or velocity-derived value); typos in XAML with a leading minus; reusable styles/templates where a theme resource accidentally becomes negative; runtime computation errors producing negative ratios.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/01774c9c02bd911f. Report an issue: GitHub.