dotnet/reactive · error · NotSupportedException

AnonymousAsyncIterator cannot be cloned. It is only…

Error message

AnonymousAsyncIterator cannot be cloned. It is only intended for use as an iterator.

What it means

AnonymousAsyncIterator is the iterator created by async LINQ operators built from lambdas/delegates; it captures compiler-generated state that cannot be duplicated. Its Clone() override therefore throws NotSupportedException stating it can only be used as an iterator. Cloning is normally an internal detail of AsyncIteratorBase used for concurrent/multiple enumeration.

Solutions

  1. Create a new enumeration per consumer: call the operator again (each call returns a fresh IAsyncEnumerable/iterator).
  2. Serialize access: enumerate sequentially or buffer results before sharing.
  3. If multiple independent streams are needed, materialize with ToListAsync and enumerate the list in parallel.

Example fix

// before
var src = AsyncEnumerable.Range(0, 10).Select(async x => x * 2);
await Task.WhenAll(Consume(src.GetEnumerator()), Consume(src.GetEnumerator())); // clones iterator
// after
var src = AsyncEnumerable.Range(0, 10).Select(x => x * 2);
await Task.WhenAll(Consume(src), Consume(src)); // fresh enumerator per call
Defensive patterns

Strategy: fallback

Validate before calling

// request a fresh enumerable per consumer instead of cloning iterators: each call to the operator returns an independent IAsyncEnumerable.

Try / catch

try { consume(it.Clone()); } catch (NotSupportedException ex) when (ex.Message.Contains("cannot be cloned")) { consume(source.GetEnumerator()); }

Prevention

When it happens

Trigger: Enumerating (or re-enumerating concurrently) an async operator result whose iterator is an AnonymousAsyncIterator in a path that calls Clone(), such as multiple simultaneous MoveNextAsync consumers or code that explicitly clones the iterator.

Common situations: Sharing one IAsyncEnumerable across parallel consumers expecting independent iterators, calling GetEnumerator/Clone directly, or custom operators deriving from AnonymousAsyncIterator and being enumerated more than once concurrently.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Linq.Async/System/Linq/AsyncEnumerator.cs:79

        private sealed class AnonymousAsyncIterator<T> : AsyncIterator<T>
        {
            private readonly Func<T> _currentFunc;
            private readonly Func<ValueTask<bool>> _moveNext;
            private Func<ValueTask>? _dispose;

            public AnonymousAsyncIterator(Func<ValueTask<bool>> moveNext, Func<T> currentFunc, Func<ValueTask> dispose)
            {
                _moveNext = moveNext;
                _currentFunc = currentFunc;
                _dispose = dispose;

                // Explicit call to initialize enumerator mode
                GetAsyncEnumerator(default);
            }

            public override AsyncIteratorBase<T> Clone()
            {
                throw new NotSupportedException("AnonymousAsyncIterator cannot be cloned. It is only intended for use as an iterator.");
            }

            public override async ValueTask DisposeAsync()
            {
                var dispose = Interlocked.Exchange(ref _dispose, null);

                if (dispose != null)
                {
                    await dispose().ConfigureAwait(false);
                }

                await base.DisposeAsync().ConfigureAwait(false);
            }

            protected override async ValueTask<bool> MoveNextCore()
            {
                switch (_state)
                {

View on GitHub (pinned to 94b5d5ab91)