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
- When spinWaitForCommit is true, always pass wait=true.
- If you truly want non-blocking completion, set spinWaitForCommit=false.
- 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 requesting spin-wait-for-commit, always set wait=true.
- Validate the (wait, spinWaitForCommit) combination at the call site.
- Default spinWaitForCommit to false unless explicitly needed.
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
- EndTransactional called with locks held: {sharedLockCount} s
- Transactional method call when BeginTransactional has not be
- BeginTransactional cannot be called twice (call EndTransacti
- Async operations not supported over protected epoch
- Make sure all async operations issued on this session are aw
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/66d27a4d555ac29e.
Report an issue: GitHub.