{"record":{"id":"da2c11403e6c2f07","repo":"OrchardCMS/OrchardCore","slug":"unexpected-shell-state-for-settings-name","errorCode":null,"errorMessage":"Unexpected shell state for {settings.Name}","messagePattern":"Unexpected shell state for (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore/Shell/ShellHost.cs","lineNumber":410,"sourceCode":"            if (_logger.IsEnabled(LogLevel.Debug))\n            {\n                _logger.LogDebug(\"Creating disabled shell context for tenant '{TenantName}'\", settings.Name);\n            }\n\n            return Task.FromResult(new ShellContext { Settings = settings });\n        }\n        else if (settings.IsRunning() || settings.IsInitializing())\n        {\n            if (_logger.IsEnabled(LogLevel.Debug))\n            {\n                _logger.LogDebug(\"Creating shell context for tenant '{TenantName}'\", settings.Name);\n            }\n\n            return _shellContextFactory.CreateShellContextAsync(settings);\n        }\n        else\n        {\n            throw new InvalidOperationException(\"Unexpected shell state for \" + settings.Name);\n        }\n    }\n\n    /// <summary>\n    /// Creates a transient shell for the default tenant's setup.\n    /// </summary>\n    private async Task<ShellContext> CreateSetupContextAsync(ShellSettings defaultSettings)\n    {\n        if (_logger.IsEnabled(LogLevel.Debug))\n        {\n            _logger.LogDebug(\"Creating shell context for root setup.\");\n        }\n\n        if (defaultSettings is null)\n        {\n            // Creates a default shell settings based on the configuration.\n            defaultSettings = _shellSettingsManager\n                .CreateDefaultSettings()","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore/Shell/ShellHost.cs#L392-L428","documentation":"CreateShellContextAsync throws InvalidOperationException when the tenant's ShellSettings state does not allow a shell context to be created — the settings are in a state not handled by the factory branches above the throw. This is an internal invariant: the shell state machine reached an unhandled combination.","triggerScenarios":"Requesting a shell context (GetOrCreateShellContextAsync) for a tenant whose ShellSettings state is unexpected — e.g. settings exist but their state flag was changed concurrently or the tenant is in an intermediate/degenerate state not covered by the factory logic.","commonSituations":"Concurrent modification of ShellSettings while requests are being served; a tenant being removed or state-transitioned during request handling; custom code that mutates ShellSettings.State directly.","solutions":["Log settings.Name and its State value to identify which state reached the unhandled branch.","Ensure tenant state changes go through ShellHost APIs instead of mutating ShellSettings directly.","Avoid removing or disabling tenants while traffic is in flight; quiesce requests first.","Retry after the concurrent state transition completes — this is often a race, not a persistent condition."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Inspect the tenant state before requesting a shell context\nif (settings.State is not (TenantState.Running or TenantState.Uninitialized or TenantState.Building))\n{\n    _logger.LogWarning(\"Tenant {Name} in unexpected state {State}; skipping shell creation.\", settings.Name, settings.State);\n    return;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var context = await _shellHost.GetOrCreateShellContextAsync(settings);\n}\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Unexpected shell state\"))\n{\n    _logger.LogWarning(ex, \"Shell state race for tenant {Name}; retrying.\", settings.Name);\n    // retry once after the concurrent transition completes\n}","preventionTips":["Change tenant state only via ShellHost/ShellSettingsManager APIs, never by mutating ShellSettings directly.","Avoid removing/disabling tenants during live request processing.","Log ShellSettings.State on failure to diagnose which state reached the unhandled branch."],"tags":["multi-tenancy","shell","state-machine"],"backgroundTag":"internal-invariant-violation","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"}