{"record":{"id":"1710a6a87b3afc46","repo":"apache/superset","slug":"changing-this-dataset-is-forbidden","errorCode":null,"errorMessage":"Changing this dataset is forbidden.","messagePattern":"Changing this dataset is forbidden\\.","errorType":"exception","errorClass":"DatasetColumnForbiddenError","httpStatus":500,"severity":"error","filePath":"superset/commands/dataset/columns/delete.py","lineNumber":57,"sourceCode":"        self._model_id = model_id\n        self._model: Optional[TableColumn] = None\n\n    @transaction(on_error=partial(on_error, reraise=DatasetColumnDeleteFailedError))\n    def run(self) -> None:\n        self.validate()\n        assert self._model\n        DatasetColumnDAO.delete([self._model])\n\n    def validate(self) -> None:\n        # Validate/populate model exists\n        self._model = DatasetDAO.find_dataset_column(self._dataset_id, self._model_id)\n        if not self._model:\n            raise DatasetColumnNotFoundError()\n        # Check editorship\n        try:\n            security_manager.raise_for_editorship(self._model)\n        except SupersetSecurityException as ex:\n            raise DatasetColumnForbiddenError() from ex\n","sourceCodeStart":39,"sourceCodeEnd":58,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/dataset/columns/delete.py#L39-L58","documentation":"DatasetColumnForbiddenError (HTTP 403, 'Changing this dataset is forbidden.') is raised when security_manager.raise_for_editorship(self._model) throws a SupersetSecurityException during column deletion. Only users who are editors (or owners) of the dataset may mutate its columns; read access to the dataset or the database is not sufficient.","triggerScenarios":"DELETE /api/v1/dataset/<dataset_id>/column/<column_id> by a user who can view the dataset but is not in its editors/owners; a Gamma user without the dataset-owner grant; ownership transferred away from the calling user before the request.","commonSituations":"Curator/viewer roles attempting schema cleanup; ownership reassigned during offboarding; service accounts that were granted read-only dataset access being reused for mutation calls.","solutions":["Have an owner/editor of the dataset perform the deletion, or add the calling user to the dataset's editors/owners first (PATCH the dataset or use the roles UI).","Verify current ownership with GET /api/v1/dataset/<id> (owners/editors fields) before retrying.","Admins can perform the operation directly since Admin is fully trusted."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Check editorship before attempting the delete\nfrom superset import security_manager\nfrom superset.daos.dataset import DatasetDAO\n\ndef can_edit_column(dataset_id: int, column_id: int) -> bool:\n    col = DatasetDAO.find_dataset_column(dataset_id, column_id)\n    if col is None:\n        return False\n    try:\n        security_manager.raise_for_editorship(col)\n        return True\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"from superset.commands.dataset.columns.exceptions import (\n    DatasetColumnForbiddenError, DatasetColumnNotFoundError,\n)\ntry:\n    DeleteDatasetColumnCommand(dataset_id, column_id).run()\nexcept DatasetColumnForbiddenError:\n    prompt_user_to_contact_owner(dataset_id)  # 403: not editor — never retry\nexcept DatasetColumnNotFoundError:\n    pass","preventionTips":["Restrict column-mutation UI/actions to users in the dataset's editors/owners.","Store the dataset owner alongside client state so 403s can be explained with a contact.","Don't reuse read-scoped service accounts for schema mutation calls."],"tags":["dataset","authorization","rbac","column","flask-api"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}