microsoft/FASTER · error · FasterException

Unexpected OperationType

Error message

Unexpected OperationType

What it means

When FASTER resumes a pending operation during InternalCompletePendingRequestFromContext, it switches on pendingContext.type (READ, RMW, CONDITIONAL_INSERT). Any other OperationType reaching this code path means internal bookkeeping is corrupt, so the library throws FasterException as an invariant failure rather than continuing. User code almost never causes this directly; it indicates a bug or corrupted pending-context state.

Solutions

  1. Capture the pendingContext.type value and file/reproduce as a FASTER bug; this is not a user-recoverable condition.
  2. Update to the latest FASTER build; several pending-operation continuation bugs have been fixed upstream.
  3. Avoid sharing pending contexts across sessions/threads and ensure every StartRequest context is created by the same session that completes it.

Example fix

// before
// completing a request whose context was built by another session
otherCtx.pendingContext = myCtx.pendingContext;
session.CompletePending(false);
// after
// let each session own and complete its own pending contexts
myCtx.session.CompletePending(false);
Defensive patterns

Strategy: try-catch

Try / catch

try { session.CompletePendingWithOutputs(out completed, wait: true); }
catch (FasterException ex) when (ex.Message == "Unexpected OperationType")
{ logger.LogCritical(ex, "FASTER internal invariant failure: corrupt pending context"); throw; }

Prevention

When it happens

Trigger: Calling status/CompletePending paths while a pending context holds an unexpected operation type (e.g. OperationType.UPSERT or NONE stored in pendingContext), typically from an internal state bug, mixed-session misuse, or memory corruption.

Common situations: Debugging after a crash-recovery resume, using Unsafe for odd record sizes with a mismatched session, or running a version with a known FASTER bug in pending-request continuation.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at cs/src/core/Index/FASTER/FASTERThread.cs:220

        internal Status InternalCompletePendingRequestFromContext<Input, Output, Context, FasterSession>(FasterSession fasterSession, AsyncIOContext<Key, Value> request,
                                                                    ref PendingContext<Input, Output, Context> pendingContext, out AsyncIOContext<Key, Value> newRequest)
            where FasterSession : IFasterSession<Key, Value, Input, Output, Context>
        {
            Debug.Assert(epoch.ThisInstanceProtected(), "InternalCompletePendingRequestFromContext requires epoch acquision");
            newRequest = default;

            // If NoKey, we do not have the key in the initial call and must use the key from the satisfied request.
            // With the new overload of CompletePending that returns CompletedOutputs, pendingContext must have the key.
            if (pendingContext.NoKey && pendingContext.key == default)
                pendingContext.key = hlog.GetKeyContainer(ref hlog.GetContextRecordKey(ref request));
            ref Key key = ref pendingContext.key.Get();

            OperationStatus internalStatus = pendingContext.type switch
            {
                OperationType.READ => ContinuePendingRead(request, ref pendingContext, fasterSession),
                OperationType.RMW => ContinuePendingRMW(request, ref pendingContext, fasterSession),
                OperationType.CONDITIONAL_INSERT => ContinuePendingConditionalCopyToTail(request, ref pendingContext, fasterSession),
                _ => throw new FasterException("Unexpected OperationType")
            };

            var status = HandleOperationStatus(fasterSession.Ctx, ref pendingContext, internalStatus, out newRequest);

            // If done, callback user code
            if (status.IsCompletedSuccessfully)
            {
                if (pendingContext.type == OperationType.READ)
                {
                    fasterSession.ReadCompletionCallback(ref key,
                                                     ref pendingContext.input.Get(),
                                                     ref pendingContext.output,
                                                     pendingContext.userContext,
                                                     status,
                                                     new RecordMetadata(pendingContext.recordInfo, pendingContext.logicalAddress));
                }
                else
                {

View on GitHub (pinned to 321d872eab)