Unity-Technologies/ml-agents · error · InvalidOperationException

Enumerator has reached the end already.

Error message

Enumerator has reached the end already.

What it means

The ActionSegment<T>.Enumerator's Current getter throws InvalidOperationException when m_Current has advanced past m_End, meaning MoveNext() already returned false and the caller keeps reading Current. Standard .NET behavior: enumeration finished but Current accessed again.

Source

Thrown at com.unity.ml-agents/Runtime/Actuators/ActionSegment.cs:217

            public bool MoveNext()
            {
                if (m_Current < m_End)
                {
                    m_Current++;
                    return m_Current < m_End;
                }
                return false;
            }

            public T Current
            {
                get
                {
                    if (m_Current < m_Start)
                        throw new InvalidOperationException("Enumerator not started.");
                    if (m_Current >= m_End)
                        throw new InvalidOperationException("Enumerator has reached the end already.");
                    return m_Array[m_Current];
                }
            }

            object IEnumerator.Current => Current;

            void IEnumerator.Reset()
            {
                m_Current = m_Start - 1;
            }

            public void Dispose()
            {
            }
        }
    }
}

View on GitHub (pinned to 3ecb446f75)

Solutions

  1. Stop reading Current once MoveNext() returns false
  2. Guard iteration in a while(e.MoveNext()) loop
  3. Check segment Length > 0 before enumerating

Example fix

// before
e.MoveNext();
var v = e.Current; // after end
// after
while (e.MoveNext()) { var v = e.Current; }
Defensive patterns

Strategy: try-catch

Validate before calling

while (e.MoveNext()) { Use(e.Current); } // never read Current outside a successful MoveNext

Try / catch

try { var v = e.Current; } catch (InvalidOperationException) { /* enumerator exhausted; stop */ }

Prevention

When it happens

Trigger: Calling Current after MoveNext() returned false — e.g. an unbounded while loop reading Current after exhausting the segment, or reading Current twice past the end.

Common situations: Loops that forget to break when MoveNext() returns false; nested foreach misuse; iterating a zero-length segment and unconditionally accessing Current.

Related errors


AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02). Data as JSON: /api/errors/bc1bc8f2d76e2cd5. Report an issue: GitHub.