{"record":{"id":"4501a0444cc5554d","repo":"OrchardCMS/OrchardCore","slug":"cannot-perform-this-operation-because-the-shell-scope-for","errorCode":null,"errorMessage":"Cannot perform this operation because the shell scope for tenant '{ShellContext.Settings.Name}' is already terminating.","messagePattern":"Cannot perform this operation because the shell scope for tenant '(.+?)' is already terminating\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.Abstractions/Shell/Scope/ShellScope.cs","lineNumber":594,"sourceCode":"\n        Terminate();\n    }\n\n    private static void Terminate()\n    {\n        var holder = s_current.Value;\n        if (holder is not null)\n        {\n            // Clear the current scope that may be trapped in some execution contexts.\n            holder.Scope = null;\n        }\n    }\n\n    private void ThrowIfTerminating()\n    {\n        if (_state.HasFlag(ShellScopeStates.IsTerminating))\n        {\n            throw new InvalidOperationException(\n                $\"Cannot perform this operation because the shell scope for tenant '{ShellContext.Settings.Name}' is already terminating.\");\n        }\n    }\n\n    private sealed class ShellScopeHolder\n    {\n        public ShellScope Scope;\n    }\n\n    [Flags]\n    private enum ShellScopeStates : byte\n    {\n        ServiceScopeOnly = 1,\n        IsTerminating = 2,\n        IsDisposed = 4,\n    }\n}\n","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.Abstractions/Shell/Scope/ShellScope.cs#L576-L612","documentation":"ShellScope throws this InvalidOperationException when an operation (container registration, signal, or deferred task) is attempted on a shell scope that is already shutting down. It guards against mutating or relying on a scope whose disposal/termination has begun. This prevents work being enqueued into a scope that will never complete.","triggerScenarios":"Calling AddDeferredSignalAsync, AddDeferredTaskAsync, or using the scope's exception handler / container operations after the scope has entered the IsTerminating state (e.g., during request teardown or shell release).","commonSituations":"Background work scheduling during host shutdown; a signal or deferred task fired from a handler while the tenant is being recycled; race between middleware disposal and application code touching the scope.","solutions":["Check ShellScope.IsTerminating (or catch the exception) before deferring signals/tasks","Move deferred task/signal scheduling earlier in the request pipeline","Ensure background services use their own scope via IScopeService rather than a terminating request scope","Retry the operation in a fresh scope after termination completes"],"exampleFix":"// before\nawait _shellScope.AddDeferredTaskAsync(myTask);\n// after\nif (!_shellScope.IsTerminating)\n{\n    await _shellScope.AddDeferredTaskAsync(myTask);\n}","handlingStrategy":"try-catch","validationCode":"if (shellScope.IsTerminating) { return; }","typeGuard":"bool canUseScope = shellScope is { IsTerminating: false };","tryCatchPattern":"try { await scope.AddDeferredTaskAsync(task); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"already terminating\")) { /* schedule after shutdown or drop */ }","preventionTips":["Check scope state before deferring work","Avoid scheduling deferred tasks in disposal/shutdown paths","Use dedicated background scopes for long-running work"],"tags":["shell","lifecycle","orchardcore"],"backgroundTag":"invalid-state-transition","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}