{"record":{"id":"63bb89f615e6d64f","repo":"OrchardCMS/OrchardCore","slug":"can-t-resolve-a-scope-on-tenant-settings-name-as-the-shell","errorCode":null,"errorMessage":"Can't resolve a scope on tenant '{Settings.Name}' as the shell context is already terminated","messagePattern":"Can't resolve a scope on tenant '(.+?)' as the shell context is already terminated","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.Abstractions/Shell/Builders/ShellContext.cs","lineNumber":259,"sourceCode":"    }\n\n    internal void AddRef()\n    {\n        // The service provider is null if we try to create\n        // a scope on a disabled shell or already disposed.\n        if (ServiceProvider is null)\n        {\n            throw new InvalidOperationException(\n               $\"Can't resolve a scope on tenant '{Settings.Name}' as it is disabled or disposed\");\n        }\n\n        int current;\n        do\n        {\n            current = _refCount;\n            if (current < 0)\n            {\n                throw new InvalidOperationException(\n                   $\"Can't resolve a scope on tenant '{Settings.Name}' as the shell context is already terminated\");\n            }\n            // Try to increment _refCount only if it is not <= -1\n        }\n        while (Interlocked.CompareExchange(ref _refCount, current + 1, current) != current);\n\n        if (Interlocked.CompareExchange(ref _terminated, 0, 0) != 0)\n        {\n            // If terminated, decrement back and throw\n            Interlocked.Decrement(ref _refCount);\n\n            throw new InvalidOperationException(\n               $\"Can't resolve a scope on tenant '{Settings.Name}' as the shell context is already terminated\");\n        }\n    }\n\n    internal bool Release()\n    {","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.Abstractions/Shell/Builders/ShellContext.cs#L241-L277","documentation":"AddRef uses an interlocked compare-exchange loop on _refCount. A negative _refCount marks a terminated shell context (Release terminated it), so any further AddRef attempts throw InvalidOperationException because scopes can no longer be created on a terminated shell.","triggerScenarios":"Calling AddRef (via ShellScope creation) after the ShellContext was terminated by Release, e.g. a concurrent request or background task grabbing a scope while the shell is being unloaded/rebuilt.","commonSituations":"Race between tenant reload and in-flight code, cached ShellContext references outliving termination, singletons capturing the shell during application shutdown.","solutions":["Do not cache ShellContext across operations; obtain it from the shell host each time so a rebuilt shell is used.","Guard scope creation with a terminated/shell-running check before calling AddRef.","Wrap scope creation in try/catch InvalidOperationException and re-resolve a fresh context once.","Ensure long-running work completes or cancels before triggering tenant rebuild/termination."],"exampleFix":"// before\nvar scope = _cachedShell.AddRef(); // may throw if terminated\n// after\nvar shell = await _shellHost.GetScopeAsync(shellSettings);\nusing var scope = shell.CreateScope();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { using var scope = shellContext.CreateScope(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already terminated\")) { shellContext = await _shellHost.GetShellContextAsync(settings); /* retry once */ }","preventionTips":["Obtain ShellContext per operation from IShellHost, never cache it","Avoid overlapping tenant rebuilds with scope creation","Stop/cancel tenant-bound work before terminating its shell"],"tags":["multi-tenancy","concurrency","shell-lifecycle"],"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"}