{"record":{"id":"36858436cceec501","repo":"microsoft/FASTER","slug":"async-operations-not-supported-over-protected-epoch-368584","errorCode":null,"errorMessage":"Async operations not supported over protected epoch","messagePattern":"Async operations not supported over protected epoch","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"cs/src/core/ClientSession/ClientSession.cs","lineNumber":887,"sourceCode":"\n        /// <inheritdoc/>\n        public ValueTask CompletePendingAsync(bool waitForCommit = false, CancellationToken token = default)\n            => CompletePendingAsync(false, waitForCommit, token);\n\n        /// <inheritdoc/>\n        public async ValueTask<CompletedOutputIterator<Key, Value, Input, Output, Context>> CompletePendingWithOutputsAsync(bool waitForCommit = false, CancellationToken token = default)\n        {\n            InitializeCompletedOutputs();\n            await CompletePendingAsync(true, waitForCommit, token).ConfigureAwait(false);\n            return this.completedOutputs;\n        }\n\n        private async ValueTask CompletePendingAsync(bool getOutputs, bool waitForCommit = false, CancellationToken token = default)\n        {\n            token.ThrowIfCancellationRequested();\n\n            if (fht.epoch.ThisInstanceProtected())\n                throw new NotSupportedException(\"Async operations not supported over protected epoch\");\n\n            // Complete all pending operations on session\n            await fht.CompletePendingAsync(this.FasterSession, token, getOutputs ? this.completedOutputs : null).ConfigureAwait(false);\n\n            // Wait for commit if necessary\n            if (waitForCommit)\n                await WaitForCommitAsync(token).ConfigureAwait(false);\n        }\n\n        /// <summary>\n        /// Check if at least one synchronous request is ready for CompletePending to be called on\n        /// Returns completed immediately if there are no outstanding synchronous requests\n        /// </summary>\n        /// <param name=\"token\"></param>\n        /// <returns></returns>\n        public async ValueTask ReadyToCompletePendingAsync(CancellationToken token = default)\n        {\n            token.ThrowIfCancellationRequested();","sourceCodeStart":869,"sourceCodeEnd":905,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/ClientSession/ClientSession.cs#L869-L905","documentation":"CompletePendingAsync (and other async session APIs) must not run while the current thread holds (protects) the FASTER epoch, because an await can resume on a different thread while the epoch is still held, corrupting epoch-based memory protection. FASTER throws NotSupportedException when ThisInstanceProtected() is true.","triggerScenarios":"Calling CompletePendingAsync (or WaitForCommitAsync, which awaits it) from inside code running under session.UnsafeContext or within a lockable/protected epoch region, e.g. inside an IFunctions callback or inside (ctx.Functions) epoch protection blocks.","commonSituations":"Mixing sync epoch-protected code with async APIs: awaiting inside a 'using (session.UnsafeContext)' style protected region, or issuing async calls from within RMW/Read callbacks.","solutions":["Do not protect the epoch (call session.UnsafeContext.Dispose()/exit protection) before issuing async operations.","Use the synchronous CompletePending(wait: true) inside epoch-protected code.","Restructure so async completion happens on a thread that never protects the epoch."],"exampleFix":"// before\nusing (session.UnsafeContext)\n{\n    await session.CompletePendingAsync(); // throws\n}\n\n// after\n// exit protection first, then await\nawait session.CompletePendingAsync();","handlingStrategy":"type-guard","validationCode":"if (fht.epoch.ThisInstanceProtected())\n    throw new InvalidOperationException(\"Exit epoch protection before CompletePendingAsync\");\nawait session.CompletePendingAsync();","typeGuard":"bool EpochUnprotected(ClientSession<K, V, I, O, C, F> session) => !session.FasterKV.epoch.ThisInstanceProtected(); // via store accessor","tryCatchPattern":"try\n{\n    await session.CompletePendingAsync();\n}\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"protected epoch\"))\n{\n    session.CompletePending(wait: true); // sync fallback inside protected region\n}","preventionTips":["Never await inside UnsafeContext/epoch-protected regions or IFunctions callbacks.","Keep a code-review rule: no 'await' between EnterProtected and ExitProtected.","Use sync completion APIs inside protected regions."],"tags":["csharp","faster","async","epoch-protection"],"backgroundTag":"unsupported-operation","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}