dotnet/reactive · error · InvalidOperationException

Exception of type 'System.InvalidOperationException' was…

Error message

Exception of type 'System.InvalidOperationException' was thrown.

What it means

AsyncEnumerable.Never never produces values or completes; its enumerator's Current getter is defined to throw InvalidOperationException because accessing Current without a produced element is meaningless for this operator. This is an internal-invariant guard: there is no current element by design.

Solutions

  1. Never read Current unless MoveNextAsync returned true; for Never it never will, so treat the stream as permanently silent.
  2. Replace Never with a source that actually emits (e.g. AsyncEnumerable.Return) if you expected values.
  3. If you need an abortable silent stream, await a Task that never completes honoring the token, or use Timer-based sources instead.

Example fix

// before
var e = AsyncEnumerable.Never<int>().GetAsyncEnumerator();
var x = e.Current; // throws
// after
if (await e.MoveNextAsync()) { var x = e.Current; } // never true for Never
Defensive patterns

Strategy: validation

Validate before calling

if (await enumerator.MoveNextAsync()) { use(enumerator.Current); } // never true for Never

Type guard

bool HasCurrent(IAsyncEnumerator<T> e) => e.MoveNextAsync().AsTask().GetAwaiter().GetResult();

Try / catch

try { var v = e.Current; }
catch (InvalidOperationException) { /* Never yields: treat as no-value */ }

Prevention

When it happens

Trigger: Accessing enumerator.Current (directly or via foreach/state machine misuse) on an AsyncEnumerable.Never<TValue> enumerator — e.g. manually calling MoveNextAsync logic bypassed, or a consumer framework reading Current without a successful MoveNextAsync.

Common situations: Using Never in tests or placeholder pipelines and accidentally reading Current; combining Never with operators that assume at least one element; incorrect manual enumerator loops that don't check MoveNextAsync's result.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/5a5a1b34392fddee. Report an issue: GitHub.

Appendix: source

Thrown at Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Never.cs:38

        private sealed class NeverAsyncEnumerable<TValue> : IAsyncEnumerable<TValue>
        {
            internal static readonly NeverAsyncEnumerable<TValue> Instance = new();

            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.

                return new NeverAsyncEnumerator(cancellationToken);
            }

            private sealed class NeverAsyncEnumerator(CancellationToken token) : IAsyncEnumerator<TValue>
            {
                private readonly CancellationToken _token = token;

                private CancellationTokenRegistration _registration;
                private bool _once;

                public TValue Current => throw new InvalidOperationException();

                public ValueTask DisposeAsync()
                {
                    _registration.Dispose();
                    return default;
                }

                public ValueTask<bool> MoveNextAsync()
                {
                    if (_once)
                    {
                        return new ValueTask<bool>(false);
                    }

                    _once = true;
                    var task = new TaskCompletionSource<bool>();
                    _registration = _token.Register(state => ((TaskCompletionSource<bool>)state!).TrySetCanceled(_token), task);
                    return new ValueTask<bool>(task.Task);

View on GitHub (pinned to 94b5d5ab91)