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
- Capture the pendingContext.type value and file/reproduce as a FASTER bug; this is not a user-recoverable condition.
- Update to the latest FASTER build; several pending-operation continuation bugs have been fixed upstream.
- 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
- Never share or transfer pending contexts between sessions or threads.
- Keep FASTER package updated to pick up pending-request continuation bug fixes.
- Minimize use of exotic paths (UnsafeMode, mixed sync/async on one session) that stress the continuation switch.
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
- Invalid release by non-owner thread
- Make sure all async operations issued on this session are…
- Out of order message within session
- Unexpected status of SubscribeKV
- Cannot use BlittableParameterSerializer with non-blittable…
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)