Cysharp/UniTask · error · NotSupportedException

Use ForEachAwaitAsync instead.

Error message

Use ForEachAwaitAsync instead.

What it means

Thrown (and emitted as a compile-time error via [Obsolete(..., true)]) by the ForEachAsync extension on IUniTaskAsyncEnumerable<T> taking Func<T, UniTask>. This overload was removed because the name 'ForEachAsync' was ambiguous about whether the async action is awaited per-element. The replacement is ForEachAwaitAsync which makes the await semantics explicit.

Source

Thrown at src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/ForEach.cs:30

            Error.ThrowArgumentNullException(action, nameof(action));

            return Cysharp.Threading.Tasks.Linq.ForEach.ForEachAsync(source, action, cancellationToken);
        }

        public static UniTask ForEachAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource, Int32> action, CancellationToken cancellationToken = default)
        {
            Error.ThrowArgumentNullException(source, nameof(source));
            Error.ThrowArgumentNullException(action, nameof(action));

            return Cysharp.Threading.Tasks.Linq.ForEach.ForEachAsync(source, action, cancellationToken);
        }

        /// <summary>Obsolete(Error), Use Use ForEachAwaitAsync instead.</summary>
        [Obsolete("Use ForEachAwaitAsync instead.", true)]
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
        public static UniTask ForEachAsync<T>(this IUniTaskAsyncEnumerable<T> source, Func<T, UniTask> action, CancellationToken cancellationToken = default)
        {
            throw new NotSupportedException("Use ForEachAwaitAsync instead.");
        }

        /// <summary>Obsolete(Error), Use Use ForEachAwaitAsync instead.</summary>
        [Obsolete("Use ForEachAwaitAsync instead.", true)]
        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
        public static UniTask ForEachAsync<T>(this IUniTaskAsyncEnumerable<T> source, Func<T, int, UniTask> action, CancellationToken cancellationToken = default)
        {
            throw new NotSupportedException("Use ForEachAwaitAsync instead.");
        }

        public static UniTask ForEachAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> action, CancellationToken cancellationToken = default)
        {
            Error.ThrowArgumentNullException(source, nameof(source));
            Error.ThrowArgumentNullException(action, nameof(action));

            return Cysharp.Threading.Tasks.Linq.ForEach.ForEachAwaitAsync(source, action, cancellationToken);
        }

View on GitHub (pinned to ceac8d6946)

Solutions

  1. Rename the call from ForEachAsync to ForEachAwaitAsync (same signature).
  2. If the action is synchronous (Func<T, void>), use the non-generic ForEachAsync overload that accepts a synchronous action — that overload is not obsolete.

Example fix

// before
await source.ForEachAsync(async x => await ProcessAsync(x));

// after
await source.ForEachAwaitAsync(async x => await ProcessAsync(x));
Defensive patterns

Strategy: validation

Validate before calling

// This is a compile-time error — fix at the call site.
// Replace ForEachAsync with ForEachAwaitAsync for async actions:
await source.ForEachAwaitAsync(async x => await ProcessAsync(x));
// For synchronous actions, the non-obsolete overload is fine:
await source.ForEachAsync(x => ProcessSync(x));

Prevention

When it happens

Trigger: Calling source.ForEachAsync(async x => await ProcessAsync(x)) on an IUniTaskAsyncEnumerable<T>. The [Obsolete(true)] attribute makes this a hard compile error; the runtime throw is a fallback for reflection/dynamic invocation.

Common situations: Upgrading UniTask from a version that had this overload. Copying code from outdated tutorials or Stack Overflow answers. Migration from System.Threading.Tasks extensions where ForEachAsync is the standard name.


AI-assisted analysis of Cysharp/UniTask@ceac8d6946 (2026-08-13). Data as JSON: /api/errors/d5e11f83e544cce3. Report an issue: GitHub.