Cysharp/UniTask · error · InvalidOperationException

Not yet completed, UniTask only allow to use await.

Error message

Not yet completed, UniTask only allow to use await.

What it means

Thrown by UniTaskCompletionSourceCore<TResult>.GetResult when completedCount is zero, meaning the source has not been signaled (no TrySetResult/TrySetException/TrySetCanceled was called). UniTask is await-only by design: calling GetResult directly on an incomplete source is invalid. The guard prevents reading an uninitialized result.

Source

Thrown at src/UniTask/Assets/Plugins/UniTask/Runtime/UniTaskCompletionSource.cs:232

        public UniTaskStatus UnsafeGetStatus()
        {
            return (continuation == null || (completedCount == 0)) ? UniTaskStatus.Pending
                 : (error == null) ? UniTaskStatus.Succeeded
                 : (error is OperationCanceledException) ? UniTaskStatus.Canceled
                 : UniTaskStatus.Faulted;
        }

        /// <summary>Gets the result of the operation.</summary>
        /// <param name="token">Opaque value that was provided to the <see cref="UniTask"/>'s constructor.</param>
        // [StackTraceHidden]
        [DebuggerHidden]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public TResult GetResult(short token)
        {
            ValidateToken(token);
            if (completedCount == 0)
            {
                throw new InvalidOperationException("Not yet completed, UniTask only allow to use await.");
            }

            if (error != null)
            {
                hasUnhandledError = false;
                if (error is OperationCanceledException oce)
                {
                    throw oce;
                }
                else if (error is ExceptionHolder eh)
                {
                    eh.GetException().Throw();
                }

                throw new InvalidOperationException("Critical: invalid exception type was held.");
            }

            return result;

View on GitHub (pinned to ceac8d6946)

Solutions

  1. Ensure every code path that creates a UniTaskCompletionSource calls TrySetResult, TrySetException, or TrySetCanceled
  2. Use await instead of manually calling GetResult — UniTask is designed for await-only consumption
  3. Check status before GetResult: if (source.GetStatus(token) != UniTaskStatus.Pending) before accessing the result

Example fix

// before
var tcs = new UniTaskCompletionSourceCore<int>();
var result = tcs.GetResult(tcs.Version); // throws: not completed

// after
var tcs = new UniTaskCompletionSourceCore<int>();
tcs.TrySetResult(42);
var result = tcs.GetResult(tcs.Version); // ok
Defensive patterns

Strategy: validation

Validate before calling

if (source.GetStatus(token) == UniTaskStatus.Pending)
{
    // not ready; await instead of calling GetResult
    throw new InvalidOperationException("Source not yet completed; use await.");
}
var result = source.GetResult(token);

Prevention

When it happens

Trigger: Manually calling GetResult on a UniTaskCompletionSourceCore before it is completed. Awaiting a UniTask whose underlying source was never signaled (e.g., a forgotten TrySetResult). Using UniTask.SuppressCancellationThrow() or direct GetResult() on a task that is still pending.

Common situations: Forgetting to call TrySetResult in a callback-based adapter. A code path that creates a UniTaskCompletionSource<T> but the signaling branch is unreachable due to a logic error. Manual interaction with IUniTaskSource outside of the await pattern.

Related errors


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