{"record":{"id":"f09320ec83a9458f","repo":"OrchardCMS/OrchardCore","slug":"unable-to-reload-the-tenant-settings-name-as-too-many","errorCode":null,"errorMessage":"Unable to reload the tenant '{settings.Name}' as too many concurrent processes are trying to do so.","messagePattern":"Unable to reload the tenant '(.+?)' as too many concurrent processes are trying to do so\\.","errorType":"exception","errorClass":"ShellHostReloadException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore/Shell/ShellHost.cs","lineNumber":243,"sourceCode":"            _shellSettings[settings.Name] = settings;\n\n            if (CanRegisterShell(settings))\n            {\n                _runningShellTable.Add(settings);\n            }\n\n            // Consistency: We may have been the last to add the shell but not with the last settings.\n            var loaded = await _shellSettingsManager.LoadSettingsAsync(settings.Name);\n            if (settings.VersionId == loaded.VersionId)\n            {\n                loaded.AsDisposable().Dispose();\n                return;\n            }\n\n            settings = loaded;\n        }\n\n        throw new ShellHostReloadException(\n            $\"Unable to reload the tenant '{settings.Name}' as too many concurrent processes are trying to do so.\");\n    }\n\n    /// <summary>\n    /// Releases a shell so that a new one will be built for subsequent requests.\n    /// Note: Can be used to free up resources after a given time of inactivity.\n    /// </summary>\n    /// <param name=\"settings\">The <see cref=\"ShellSettings\"/> to reload.</param>\n    /// <param name=\"eventSource\">Whether the related <see cref=\"ShellEvent\"/> is invoked.</param>\n    public async Task ReleaseShellContextAsync(ShellSettings settings, bool eventSource = true)\n    {\n        if (ReleasingAsync is not null && eventSource && !settings.IsInitializing())\n        {\n            foreach (var d in ReleasingAsync.GetInvocationList())\n            {\n                await ((ShellEvent)d)(settings.Name);\n            }\n        }","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore/Shell/ShellHost.cs#L225-L261","documentation":"ShellHost throws ShellHostReloadException when a tenant's shell context cannot be reloaded because concurrent reload attempts exhausted the retry/lock attempts. Orchard Core serializes shell reloads so only a limited number of processes may reload a given tenant at once; when the concurrency guard gives up, this error is raised to protect against an inconsistent shell state.","triggerScenarios":"Calling UpdateShellSettingsAsync (or ReloadShellContextAsync directly) for the same tenant from multiple concurrent requests/threads, e.g. updating tenant settings while background tasks or several admin requests simultaneously trigger a reload of that tenant.","commonSituations":"Admin UI saves tenant settings while another request reloads the shell; automated scripts updating many tenants in parallel; a slow reload (long tenant startup) exceeding the retry window so other reload attempts time out and throw.","solutions":["Avoid issuing concurrent updates/reloads to the same tenant; serialize tenant settings updates in your code.","Retry the operation after a short delay — the error is transient by design (the reload was blocked, not failed).","Reduce slow startup work in tenant modules so reloads finish quickly and stop colliding.","If triggered by parallel scripts, run tenant updates sequentially or use a lock around UpdateShellSettingsAsync."],"exampleFix":"// before: parallel\nawait Task.WhenAll(tenants.Select(t => _shellHost.UpdateShellSettingsAsync(t)));\n// after: sequential with retry\nforeach (var t in tenants)\n{\n    try { await _shellHost.UpdateShellSettingsAsync(t); }\n    catch (ShellHostReloadException) { await Task.Delay(500); await _shellHost.UpdateShellSettingsAsync(t); }\n}","handlingStrategy":"retry","validationCode":"// Track in-flight reloads per tenant in application code\nprivate static readonly HashSet<string> _reloading = new();\nlock (_reloading) { if (_reloading.Contains(name)) return; _reloading.Add(name); }\ntry { await shellHost.UpdateShellSettingsAsync(settings); }\nfinally { lock (_reloading) _reloading.Remove(name); }","typeGuard":null,"tryCatchPattern":"try\n{\n    await _shellHost.UpdateShellSettingsAsync(settings);\n}\ncatch (ShellHostReloadException ex)\n{\n    _logger.LogWarning(ex, \"Tenant {Tenant} reload was blocked by concurrent reloads; retrying.\", settings.Name);\n    await Task.Delay(Random.Shared.Next(250, 1000));\n    await _shellHost.UpdateShellSettingsAsync(settings);\n}","preventionTips":["Never update the same tenant's settings concurrently; queue or lock per-tenant updates.","Serialize tenant administrative operations in scripts instead of parallelizing them.","Keep tenant startup light so reload windows are short.","Treat ShellHostReloadException as transient and retry with backoff."],"tags":["multi-tenancy","concurrency","shell"],"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-15T23:17:13.987Z"}