microsoft/FASTER · error · FasterException

Make sure all async operations issued on this session are…

Error message

Make sure all async operations issued on this session are awaited and completed first

What it means

WaitForCommitAsync waits for an ongoing checkpoint to become durable, but the session's execution contexts still hold uncompleted pending reads. FASTER throws FasterException to avoid waiting for a commit while async reads issued on the session have not been awaited/completed.

Solutions

  1. Await every async Read's returned ValueTask (var (status, output) = await task;) before WaitForCommitAsync.
  2. Call await session.CompletePendingAsync() (or CompletePendingAsync(waitForCommit: true) directly) before WaitForCommitAsync.
  3. Use CompletePendingAsync(waitForCommit: true) to combine completion and commit waiting in one call.

Example fix

// before
session.ReadAsync(input, key, ctx); // not awaited
await session.WaitForCommitAsync(); // throws

// after
var result = await session.ReadAsync(input, key, ctx);
await session.WaitForCommitAsync();
Defensive patterns

Strategy: validation

Validate before calling

// ensure no un-awaited async reads remain
await session.CompletePendingAsync(); // completes and drains pendingReads
await session.WaitForCommitAsync();

Try / catch

try
{
    await session.WaitForCommitAsync();
}
catch (FasterException ex) when (ex.Message.Contains("async operations"))
{
    await session.CompletePendingAsync(waitForCommit: true);
}

Prevention

When it happens

Trigger: Calling session.WaitForCommitAsync() while ctx.pendingReads or ctx.prevCtx.pendingReads is non-empty — i.e. async Read operations were issued (returned a ValueTask that was not awaited or CompletePendingAsync not yet run for them).

Common situations: Fire-and-forget async reads (not awaiting the returned ValueTask) followed by WaitForCommitAsync before checkpoint; forgetting to CompletePendingAsync between reads and commit wait.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/18ce2cb6d23aee47. Report an issue: GitHub.

Appendix: source

Thrown at cs/src/core/ClientSession/ClientSession.cs:965

                status = fht.InternalModifiedBitOperation(ref key, out modifiedInfo, false);
            while (fht.HandleImmediateNonPendingRetryStatus<Input, Output, Context, InternalFasterSession>(status, FasterSession));
            return modifiedInfo.Modified;
        }

        /// <inheritdoc/>
        internal unsafe bool IsModified(Key key) => IsModified(ref key);

        /// <summary>
        /// Wait for commit of all operations completed until the current point in session.
        /// Does not itself issue checkpoint/commits.
        /// </summary>
        /// <returns></returns>
        public async ValueTask WaitForCommitAsync(CancellationToken token = default)
        {
            token.ThrowIfCancellationRequested();

            if (!ctx.prevCtx.pendingReads.IsEmpty || !ctx.pendingReads.IsEmpty)
                throw new FasterException("Make sure all async operations issued on this session are awaited and completed first");

            // Complete all pending sync operations on session
            await CompletePendingAsync(token: token).ConfigureAwait(false);

            var task = fht.CheckpointTask;
            CommitPoint localCommitPoint = LatestCommitPoint;
            if (localCommitPoint.UntilSerialNo >= ctx.serialNum && localCommitPoint.ExcludedSerialNos?.Count == 0)
                return;

            while (true)
            {
                await task.WithCancellationAsync(token).ConfigureAwait(false);
                Refresh();

                task = fht.CheckpointTask;
                localCommitPoint = LatestCommitPoint;
                if (localCommitPoint.UntilSerialNo >= ctx.serialNum && localCommitPoint.ExcludedSerialNos?.Count == 0)
                    break;

View on GitHub (pinned to 321d872eab)