dotnet/wpf · error · ArgumentOutOfRangeException

SR.Animation_KeyTime_LessThanZero

Error message

SR.Animation_KeyTime_LessThanZero

What it means

KeyTime.FromTimeSpan throws ArgumentOutOfRangeException (SR.Animation_KeyTime_LessThanZero) because a TimeSpan KeyTime marks an offset from the start of the animation and cannot be negative. Only zero or positive durations are accepted.

Solutions

  1. Clamp negative spans to zero before calling: if (ts < TimeSpan.Zero) ts = TimeSpan.Zero.
  2. Fix the calculation that produced the negative TimeSpan (guard ordering: Math.Max(0, elapsed)).
  3. Validate configured/serialized offsets for negativity before constructing key frames.
  4. Catch ArgumentOutOfRangeException and substitute KeyTime.FromTimeSpan(TimeSpan.Zero).

Example fix

// before
var kt = KeyTime.FromTimeSpan(end - start); // may be negative
// after
var delta = end - start;
var kt = KeyTime.FromTimeSpan(delta < TimeSpan.Zero ? TimeSpan.Zero : delta);
Defensive patterns

Strategy: validation

Validate before calling

if (timeSpan < TimeSpan.Zero)
    timeSpan = TimeSpan.Zero;
var kt = KeyTime.FromTimeSpan(timeSpan);

Type guard

static TimeSpan NonNegative(TimeSpan t) => t < TimeSpan.Zero ? TimeSpan.Zero : t;

Try / catch

try { kt = KeyTime.FromTimeSpan(delta); }
catch (ArgumentOutOfRangeException)
{ kt = KeyTime.FromTimeSpan(TimeSpan.Zero); }

Prevention

When it happens

Trigger: KeyTime.FromTimeSpan(ts) where ts < TimeSpan.Zero — e.g. subtracting timestamps to compute a key offset and getting a negative result.

Common situations: Computing key times from measured event times where ordering assumptions broke; user config with negative offsets; arithmetic on durations where a later value was subtracted from an earlier one.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/KeyTime.cs:50

            KeyTime keyTime = new KeyTime
            {
                _value = percent,
                _type = KeyTimeType.Percent
            };

            return keyTime;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="timeSpan"></param>
        public static KeyTime FromTimeSpan(TimeSpan timeSpan)
        {
            if (timeSpan < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(timeSpan), SR.Format(SR.Animation_KeyTime_LessThanZero, timeSpan));
            }

            KeyTime keyTime = new KeyTime
            {
                _value = timeSpan,
                _type = KeyTimeType.TimeSpan
            };

            return keyTime;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <value></value>
        public static KeyTime Uniform
        {
            get

View on GitHub (pinned to 81131a70a4)