{"record":{"id":"eb4bfe97c96ad5c2","repo":"OrchardCMS/OrchardCore","slug":"the-theme-0-is-already-in-the-stack-of-themes-that-need","errorCode":null,"errorMessage":"The theme \"{0}\" is already in the stack of themes that need features disabled.","messagePattern":"The theme \"(.+?)\" is already in the stack of themes that need features disabled\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.Themes/Services/ThemeService.cs","lineNumber":39,"sourceCode":"        IHtmlLocalizer<ThemeService> htmlLocalizer,\n        INotifier notifier)\n    {\n        _extensionManager = extensionManager;\n        _shellFeaturesManager = shellFeaturesManager;\n        _siteThemeService = siteThemeService;\n\n        _notifier = notifier;\n        H = htmlLocalizer;\n    }\n\n    public async Task DisableThemeFeaturesAsync(string themeName)\n    {\n        var themes = new Queue<string>();\n        while (themeName != null)\n        {\n            if (themes.Contains(themeName))\n            {\n                throw new InvalidOperationException(H[\"The theme \\\"{0}\\\" is already in the stack of themes that need features disabled.\", themeName].ToString());\n            }\n\n            var theme = _extensionManager.GetExtension(themeName);\n            if (theme == null)\n            {\n                break;\n            }\n\n            themes.Enqueue(themeName);\n\n            themeName = !string.IsNullOrWhiteSpace(theme.Manifest.Name)\n                ? theme.Manifest.Name\n                : null;\n        }\n\n        var currentTheme = await _siteThemeService.GetSiteThemeNameAsync();\n\n        while (themes.Count > 0)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.Themes/Services/ThemeService.cs#L21-L57","documentation":"ThemeService.DisableThemeFeaturesAsync walks the base-theme chain of the theme being disabled using a queue of theme names. If a theme name appears twice in that chain (a cycle or self-reference in the BaseTheme dependency), it throws InvalidOperationException to prevent infinite recursion.","triggerScenarios":"Calling DisableThemeFeaturesAsync for a theme whose BaseTheme chain contains a cycle (theme A bases on B, B bases on A) or where the same theme name is already queued — typically a malformed Theme attribute in the module's manifest.","commonSituations":"A custom theme accidentally setting its own name as BaseTheme; two custom themes referencing each other as base themes; corrupted recipe/manifest data after renaming a theme.","solutions":["Fix the BaseTheme declaration in the theme's manifest/ThemeAttribute so the chain terminates (no self- or mutual reference).","Set the offending theme's base theme to null or a valid acyclic parent theme.","Rebuild/redeploy the theme with the corrected manifest, then retry disabling."],"exampleFix":"// before (theme manifest)\n\"BaseTheme\": \"MyTheme\" // self-reference\n// after\n\"BaseTheme\": \"TheTheme\" // or removed entirely","handlingStrategy":"validation","validationCode":"// verify base-theme chain is acyclic before disabling\nvar seen = new HashSet<string>();\nfor (var t = themeName; t != null; t = extensionManager.GetExtension(t)?.BaseTheme) {\n  if (!seen.Add(t)) throw new InvalidOperationException($\"Base theme cycle at '{t}'\");\n}","typeGuard":"const hasAcyclicBaseChain = (name, getBase) => { const s = new Set(); for (let t = name; t; t = getBase(t)) { if (s.has(t)) return false; s.add(t); } return true; };","tryCatchPattern":"try {\n  await themeService.DisableThemeFeaturesAsync(themeName);\n} catch (InvalidOperationException ex) when (ex.Message.Contains(\"already in the stack\")) {\n  logger.LogError(ex, \"Base-theme cycle detected for {Theme}\", themeName);\n}","preventionTips":["Never set a theme's BaseTheme to itself or a descendant.","Validate theme manifests in CI (walk base chains for cycles).","Avoid manual edits of manifest BaseTheme values after renames."],"tags":["themes","cyclic-dependency","manifest","themes-module"],"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-23T08:17:48.524Z"}