dotnet/wpf · error · InvalidOperationException

SR.LocalValueEnumerationReset

Error message

SR.LocalValueEnumerationReset

What it means

LocalValueEnumerator.Current throws InvalidOperationException(SR.LocalValueEnumerationReset) when the enumerator has not been started (MoveNext never called, index still -1). This matches the IEnumerator.Current contract documented in .NET. Accessing Current before starting enumeration is a caller sequencing error.

Solutions

  1. Call MoveNext() at least once before reading Current.
  2. Prefer a foreach loop over the enumerator, which handles sequencing automatically.
  3. Restructure the loop to only access Current after MoveNext() returns true.
  4. Catch InvalidOperationException as a last resort, but fix the loop ordering instead.

Example fix

// before
var e = obj.GetLocalValueEnumerator();
var entry = e.Current; // throws: not started
// after
var e = obj.GetLocalValueEnumerator();
while (e.MoveNext())
{
    var entry = e.Current;
}
Defensive patterns

Strategy: validation

Validate before calling

bool ready = enumerator.MoveNext(); // only read Current if this returned true

Type guard

null

Try / catch

try { var cur = enumerator.Current; }
catch (InvalidOperationException) { /* enumerator not started; call MoveNext first */ }

Prevention

When it happens

Trigger: Obtaining a LocalValueEnumerator from DependencyObject.GetLocalValueEnumerator() and reading Current before the first MoveNext() call.

Common situations: Manual foreach-free iteration loops that forget the initial MoveNext; refactored code where the MoveNext call was removed or reordered; generic enumerator wrappers calling Current eagerly.

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/e62b3d800c2fb48d. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/LocalValueEnumerator.cs:70

        /// <summary>
        ///     Determine inequality
        /// </summary>
        public static bool operator !=(LocalValueEnumerator obj1, LocalValueEnumerator obj2)
        {
          return !(obj1 == obj2);
        }
        
        /// <summary>
        ///     Get current entry
        /// </summary>
        public LocalValueEntry Current
        {
            get
            {
                if(_index == -1 )
                {
                    // IEnumerator.Current is documented to throw this exception
                    throw new InvalidOperationException(SR.LocalValueEnumerationReset);
                }

                if(_index >= Count )
                {
                    // IEnumerator.Current is documented to throw this exception
                    throw new InvalidOperationException(SR.LocalValueEnumerationOutOfBounds);
                }
                
                return _snapshot[_index];
            }
        }

        /// <summary>
        ///     Get current entry (object reference based)
        /// </summary>
        object IEnumerator.Current
        {
            get { return Current; }

View on GitHub (pinned to 81131a70a4)