dotnet/wpf · error · InvalidEnumArgumentException

Enum_Invalid

Enum_Invalid

Error message

SR.Enum_Invalid: TimeSeekOrigin

What it means

ClockController.Seek validates the TimeSeekOrigin enum argument before using it. Passing a value outside TimeSeekOrigin.Begin/Duration raises InvalidEnumArgumentException with SR.Enum_Invalid formatted with "TimeSeekOrigin". This is standard enum-argument validation so the exception is thrown from the public method actually called.

Solutions

  1. Pass only TimeSeekOrigin.Begin or TimeSeekOrigin.Duration
  2. Validate the origin with TimeEnumHelper.IsValidTimeSeekOrigin(origin) or Enum.IsDefined before calling
  3. Fix the cast/source that produced the out-of-range enum value

Example fix

// before
controller.Seek(TimeSpan.FromSeconds(1), (TimeSeekOrigin)42); // throws
// after
var origin = TimeSeekOrigin.Duration;
if (TimeEnumHelper.IsValidTimeSeekOrigin(origin))
    controller.Seek(TimeSpan.FromSeconds(1), origin);
Defensive patterns

Strategy: validation

Validate before calling

bool isValidOrigin = origin == TimeSeekOrigin.Begin || origin == TimeSeekOrigin.Duration;
// or: Enum.IsDefined(typeof(TimeSeekOrigin), origin)

Type guard

static bool IsValidTimeSeekOrigin(object o) => o is TimeSeekOrigin t && (t == TimeSeekOrigin.Begin || t == TimeSeekOrigin.Duration);

Try / catch

try { controller.Seek(offset, origin); }
catch (System.ComponentModel.InvalidEnumArgumentException ex) { /* fix/normalize origin */ }

Prevention

When it happens

Trigger: Calling clock.Controller.Seek(offset, (TimeSeekOrigin)someInvalidInt) — e.g. casting an arbitrary int, deserializing a bad enum value, or passing TimeSeekOrigin values from a different enum type.

Common situations: Enum values persisted in config/XAML/bindings and cast back without validation; code generated from stale metadata where TimeSeekOrigin gained/lost members.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/ClockController.cs:156

        /// <p>The seek is measured in the Clock's simple time frame of reference, meaning that the
        /// actual wall-clock playback time skipped (or replayed) may be different than that specified
        /// by the offset parameter, if time manipulations from the Speed, Acceleration or Deceleration
        /// properties are in effect for this Clock.</p>
        ///
        /// <p>The seek operation may only span the current simple duration of the Clock. Seeking to a
        /// time earlier than the begin time positions the Clock at the begin point, whereas
        /// seeking beyond the end simply puts the Clock at the end point.</p>
        /// </remarks>
        public void Seek(TimeSpan offset, TimeSeekOrigin origin)
        {
            // IF YOU CHANGE THIS CODE:
            // This code is very similar to that in SeekAlignedToLastTick and is duplicated
            // in each method so that exceptions will be thrown from the public 
            // method the user has called. You probably need to change both methods.

            if (!TimeEnumHelper.IsValidTimeSeekOrigin(origin))
            {
                throw new InvalidEnumArgumentException(SR.Format(SR.Enum_Invalid, "TimeSeekOrigin"));
            }

            if (origin == TimeSeekOrigin.Duration)
            {
                Duration duration = _owner.ResolvedDuration;

                if (!duration.HasTimeSpan)
                {
                    // Can't seek relative to the Duration if it has been specified as Forever or if
                    // it has not yet been resolved.
                    throw new InvalidOperationException(SR.Timing_SeekDestinationIndefinite);
                }
                else
                {
                    offset += duration.TimeSpan;
                }
            }

View on GitHub (pinned to 81131a70a4)