apache/superset · error · DashboardForbiddenError
Changing this Dashboard is forbidden
Error message
Changing this Dashboard is forbidden
What it means
DashboardForbiddenError is raised by DeleteEmbeddedDashboardCommand.validate() when security_manager.raise_for_editorship(dashboard) throws SupersetSecurityException. Deleting a dashboard's embedded configuration counts as modifying the dashboard, so only owners/editors/admins may do it.
Source
Thrown at superset/commands/dashboard/delete.py:54
from superset.utils.decorators import on_error, transaction
logger = logging.getLogger(__name__)
class DeleteEmbeddedDashboardCommand(BaseCommand):
def __init__(self, dashboard: Dashboard):
self._dashboard = dashboard
@transaction(on_error=partial(on_error, reraise=DashboardDeleteEmbeddedFailedError))
def run(self) -> None:
self.validate()
return EmbeddedDashboardDAO.delete(self._dashboard.embedded)
def validate(self) -> None:
try:
security_manager.raise_for_editorship(self._dashboard)
except SupersetSecurityException as ex:
raise DashboardForbiddenError() from ex
class DeleteDashboardCommand(BaseCommand):
def __init__(self, model_ids: list[int]):
self._model_ids = model_ids
self._models: Optional[list[Dashboard]] = None
@transaction(on_error=partial(on_error, reraise=DashboardDeleteFailedError))
def run(self) -> None:
self.validate()
assert self._models
DashboardDAO.delete(self._models)
def validate(self) -> None:
# Validate/populate model exists
self._models = DashboardDAO.find_by_ids(self._model_ids)
if not self._models or len(self._models) != len(self._model_ids):
raise DashboardNotFoundError()View on GitHub (pinned to f4587218dd)
Solutions
- Perform the embedded deletion as a dashboard owner or admin user.
- For service accounts, grant a role with dashboard edit/editor permission on that dashboard.
- Check the actor in background jobs: embedded deletion in async code inherits the job's user context, which may be None or a limited user.
Example fix
# before
DeleteEmbeddedDashboardCommand(dash).run() # viewer user -> 403
# after
from superset.extensions import security_manager
try:
DeleteEmbeddedDashboardCommand(dash).run()
except DashboardForbiddenError:
# re-run as owner or surface a permission prompt
raise Defensive patterns
Strategy: try-catch
Validate before calling
from superset.extensions import security_manager
try:
security_manager.raise_for_editorship(dashboard)
except SupersetSecurityException:
raise PermissionError('editorship required to delete embedded config') Try / catch
try:
DeleteEmbeddedDashboardCommand(dashboard).run()
except DashboardForbiddenError:
# retry as owner/admin or surface permission error to user
escalate_permission_error(dashboard.id) Prevention
- Only expose embedded-config controls to editors in the UI.
- Keep background jobs' user context explicit when they touch embedded settings.
- Service accounts used for cleanup need editorship or admin.
When it happens
Trigger: Calling the embedded-delete flow (DELETE on the dashboard's embedded resource, e.g. /api/v1/dashboard/<id>/embedded) as a user who cannot edit the dashboard. Also triggered by code paths that clear embedded config during dashboard updates when the actor is a viewer.
Common situations: Non-owner admins of restricted deployments trying to disable embedded mode; automated cleanup scripts running under a low-privilege service account; embedded-guest flows that mistakenly invoke deletion.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Changing this Dashboard is forbidden
- You don't have access to this dashboard.
- Changing this Dashboard is forbidden
- Cannot convert node type: ${node.type}
- Changing this chart is forbidden
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/ad762e2096943a67.
Report an issue: GitHub.