{"record":{"id":"1e6e0fb33b9a7297","repo":"apache/superset","slug":"user-does-not-have-permission-to-update-the-theme","errorCode":null,"errorMessage":"User does not have permission to update the theme","messagePattern":"User does not have permission to update the theme","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"superset-frontend/src/theme/ThemeController.ts","lineNumber":861,"sourceCode":"        // Dark mode is valid if we have a dark theme\n        return !!this.darkTheme;\n      case ThemeMode.DEFAULT:\n        // Default mode is valid if we have a default theme\n        return !!this.defaultTheme;\n      case ThemeMode.SYSTEM:\n        // System mode is valid if dark mode is available\n        return !!this.darkTheme;\n      default:\n        return true;\n    }\n  }\n\n  /**\n   * Validates permission to update theme.\n   */\n  private validateThemeUpdatePermission(): void {\n    if (!this.canSetTheme())\n      throw new Error('User does not have permission to update the theme');\n  }\n\n  /**\n   * Validates permission to update mode.\n   * @throws {Error} If the user does not have permission to update the theme mode\n   */\n  private validateModeUpdatePermission(): void {\n    // Check if user can set a new theme mode (dark theme must exist)\n    if (!this.canSetMode())\n      throw new Error(\n        'Theme mode changes are not allowed when only one theme is available',\n      );\n  }\n\n  /**\n   * Applies the current theme configuration to the global theme.\n   * This method sets the theme on the globalTheme and applies it to the Theme.\n   * It also handles any errors that may occur during the application of the theme.","sourceCodeStart":843,"sourceCodeEnd":879,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset-frontend/src/theme/ThemeController.ts#L843-L879","documentation":"ThemeController.validateThemeUpdatePermission throws when canSetTheme() is false — i.e. the current principal is not allowed to change the theme configuration. It is the guard called before any setTheme* mutation, so calling those methods as a user/extension without theme permission always fails here.","triggerScenarios":"Calling themeController.setThemeConfig / setTheme while the running user lacks the theme-management permission (canSetTheme() false); embedded guest or restricted role invoking a theme API; programmatic theming from a plugin without checking permission first.","commonSituations":"Custom roles without the theme capability; embedded dashboards where the host app pushes setThemeConfig over the Switchboard but the guest session cannot set themes; permission changes after rollout of themed dashboards.","solutions":["Grant the user/role the theme-management permission (or run as a role that has it) before calling setTheme*.","Guard the call: if (!themeController.canSetTheme()) skip or show an explanatory message.","In embedded setups, only send setThemeConfig when the guest token grants theme capabilities.","Catch this error at the boundary (e.g. embedded setThemeConfig method) and return a structured failure to the host."],"exampleFix":"// before\nthemeController.setThemeConfig(newConfig);\n\n// after\nif (!themeController.canSetTheme()) {\n  addDangerToast(t('You do not have permission to change the theme'));\n  return;\n}\nthemeController.setThemeConfig(newConfig);","handlingStrategy":"validation","validationCode":"if (!themeController.canSetTheme()) {\n  // hide/disable theme controls instead of calling setTheme*\n  return;\n}\nthemeController.setThemeConfig(config);","typeGuard":null,"tryCatchPattern":"try {\n  themeController.setThemeConfig(config);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('permission')) {\n    addDangerToast(t('You cannot change the theme'));\n    return;\n  }\n  throw e;\n}","preventionTips":["Gate theme UI behind canSetTheme() so unauthorized users never trigger the throw.","In embedded hosts, check guest capabilities before sending setThemeConfig/setThemeMode.","Keep theme permission grants aligned with the roles that own theming."],"tags":["theme","permissions","rbac","theming"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}