microsoft/garnet · error · TsavoriteException

Can spin-wait for commit (checkpoint completion) only if wai

Error message

Can spin-wait for commit (checkpoint completion) only if wait is true

What it means

UnsafeCompletePending accepts both a 'wait' flag and a 'spinWaitForCommit' flag. spinWaitForCommit=true means the caller wants to block-spin until the store enters its REST phase (checkpoint completion). This only makes sense if wait is also true — spin-waiting without waiting is contradictory and indicates a logic error. The throw catches this contradictory parameter combination early.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/ClientSession/ClientSession.cs:297

            try
            {
                return UnsafeCompletePending(sessionFunctions, getOutputs, wait, spinWaitForCommit);
            }
            finally
            {
                UnsafeSuspendThread();
            }
        }

        internal bool UnsafeCompletePending<TSessionFunctionsWrapper>(TSessionFunctionsWrapper sessionFunctions, bool getOutputs, bool wait, bool spinWaitForCommit)
            where TSessionFunctionsWrapper : ISessionFunctionsWrapper<TInput, TOutput, TContext, TStoreFunctions, TAllocator>
        {
            var requestedOutputs = getOutputs ? completedOutputs : default;
            var result = store.InternalCompletePending(sessionFunctions, wait, requestedOutputs);
            if (spinWaitForCommit)
            {
                if (!wait)
                    throw new TsavoriteException("Can spin-wait for commit (checkpoint completion) only if wait is true");
                do
                {
                    _ = store.InternalCompletePending(sessionFunctions, wait, requestedOutputs);
                    if (store.InRestPhase())
                    {
                        _ = store.InternalCompletePending(sessionFunctions, wait, requestedOutputs);
                        return true;
                    }
                } while (wait);
            }
            return result;
        }

        /// <inheritdoc/>
        internal ValueTask CompletePendingAsync<TSessionFunctionsWrapper>(TSessionFunctionsWrapper sessionFunctions, bool waitForCommit = false, CancellationToken token = default)
            where TSessionFunctionsWrapper : ISessionFunctionsWrapper<TInput, TOutput, TContext, TStoreFunctions, TAllocator>
            => CompletePendingAsync(sessionFunctions, getOutputs: false, waitForCommit, token);

View on GitHub (pinned to 951b0fc683)

Solutions

  1. When spinWaitForCommit is true, always pass wait=true.
  2. If you truly want non-blocking completion, set spinWaitForCommit=false.
  3. Validate the flag combination before calling: if (spinWaitForCommit && !wait) throw or correct the flags.

Example fix

// before
session.UnsafeCompletePending(funcs, getOutputs: true, wait: false, spinWaitForCommit: true);

// after
session.UnsafeCompletePending(funcs, getOutputs: true, wait: true, spinWaitForCommit: true);
Defensive patterns

Strategy: validation

Validate before calling

if (spinWaitForCommit && !wait) throw new ArgumentException("spinWaitForCommit requires wait=true.", nameof(spinWaitForCommit));

Prevention

When it happens

Trigger: Calling UnsafeCompletePending (or a higher-level API that forwards these flags) with spinWaitForCommit=true and wait=false.

Common situations: Passing spinWaitForCommit through from user options without also setting wait=true; code that defaults wait=false but conditionally enables spin-wait-for-commit.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/66d27a4d555ac29e. Report an issue: GitHub.