apache/superset · error · DatasetForbiddenError

Changing this dataset is forbidden

Error message

Changing this dataset is forbidden

What it means

DatasetForbiddenError (HTTP 403, 'Changing this dataset is forbidden') is raised by the dataset delete command when security_manager.raise_for_editorship(model) throws for any model in the bulk set. Every dataset in the delete payload must be editable by the caller; a single non-editable dataset blocks the entire bulk delete.

Source

Thrown at superset/commands/dataset/delete.py:57

        self._models: Optional[list[SqlaTable]] = None

    @transaction(on_error=partial(on_error, reraise=DatasetDeleteFailedError))
    def run(self) -> None:
        self.validate()
        assert self._models
        DatasetDAO.delete(self._models)

    def validate(self) -> None:
        # Validate/populate model exists
        self._models = DatasetDAO.find_by_ids(self._model_ids)
        if not self._models or len(self._models) != len(self._model_ids):
            raise DatasetNotFoundError()
        # Check editorship
        for model in self._models:
            try:
                security_manager.raise_for_editorship(model)
            except SupersetSecurityException as ex:
                raise DatasetForbiddenError() from ex

View on GitHub (pinned to f4587218dd)

Solutions

  1. Split the request: delete only datasets where the caller is owner/editor; leave the rest to their owners (or an Admin).
  2. Check owners/editors per dataset via GET /api/v1/dataset/?q=(id:...) before building the bulk payload.
  3. If the operation is legitimately centralized, perform it as Admin or grant the caller ownership of the affected datasets first.
Defensive patterns

Strategy: validation

Validate before calling

# Partition the bulk set by editorship before deleting
from superset import security_manager
from superset.daos.dataset import DatasetDAO

def split_by_editorship(ids: list[int]) -> tuple[list[int], list[int]]:
    editable, forbidden = [], []
    for model in DatasetDAO.find_by_ids(ids) or []:
        try:
            security_manager.raise_for_editorship(model)
            editable.append(model.id)
        except Exception:
            forbidden.append(model.id)
    return editable, forbidden

Try / catch

from superset.commands.dataset.exceptions import DatasetForbiddenError
editable, forbidden = split_by_editorship(ids)
try:
    DeleteDatasetsCommand(editable).run()
except DatasetForbiddenError:
    # ownership changed mid-flight: re-partition and retry the remainder once
    editable2, forbidden2 = split_by_editorship(editable)
    if editable2:
        DeleteDatasetsCommand(editable2).run()

Prevention

When it happens

Trigger: DELETE /api/v1/dataset/ with multiple ids where the caller owns some but not all; a user with dataset read access attempting deletion; ownership of one dataset in the selection belonging to another user.

Common situations: Bulk cleanup across teams where a mixed set of owned/unowned datasets is selected; service accounts with broad read grants but no editorship; Gamma users deleting shared datasets.

Understand the failure class

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/c6d58ae198d4da76. Report an issue: GitHub.