{"record":{"id":"1d525f7826ccd0e4","repo":"apache/superset","slug":"changing-this-chart-is-forbidden","errorCode":null,"errorMessage":"Changing this chart is forbidden","messagePattern":"Changing this chart is forbidden","errorType":"exception","errorClass":"ChartForbiddenError","httpStatus":403,"severity":"error","filePath":"superset/commands/chart/create.py","lineNumber":78,"sourceCode":"        self._properties[\"last_saved_by\"] = g.user\n        chart = ChartDAO.create(attributes=self._properties)\n        if after_create := current_app.config.get(\"AFTER_ASSET_CREATE\"):\n            after_create(chart, \"chart\")\n        return chart\n\n    def validate(self) -> None:\n        exceptions = []\n        datasource_type = self._properties[\"datasource_type\"]\n        datasource_id = self._properties[\"datasource_id\"]\n        dashboard_ids = self._properties.get(\"dashboards\", [])\n\n        # Validate/Populate datasource\n        try:\n            datasource = get_datasource_by_id(datasource_id, datasource_type)\n            self._properties[\"datasource_name\"] = datasource.name\n            security_manager.raise_for_access(datasource=datasource)\n        except SupersetSecurityException as ex:\n            raise ChartForbiddenError() from ex\n        except ValidationError as ex:\n            exceptions.append(ex)\n\n        # Validate/Populate dashboards\n        dashboards = DashboardDAO.find_by_ids(dashboard_ids)\n        if len(dashboards) != len(dashboard_ids):\n            exceptions.append(DashboardsNotFoundValidationError())\n        for dash in dashboards:\n            if not security_manager.is_editor(dash):\n                raise DashboardsForbiddenError()\n        self._properties[\"dashboards\"] = dashboards\n\n        populate_subjects(self._properties, exceptions)\n\n        if exceptions:\n            raise ChartInvalidError(exceptions=exceptions)\n","sourceCodeStart":60,"sourceCodeEnd":95,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/chart/create.py#L60-L95","documentation":"ChartForbiddenError (ForbiddenError subclass, HTTP 403) raised in ChartCreateCommand.validate() when security_manager.raise_for_access(datasource=...) throws SupersetSecurityException while resolving the chart's datasource. Creating a chart requires the caller to have access to the target dataset; the original security exception is chained via 'from ex'.","triggerScenarios":"POST /api/v1/chart/ with datasource_id/datasource_type the user cannot access (no dataset permission, RLS-blocked, Gamma without 'can read on dataset'); referencing a dataset in a database the role cannot query.","commonSituations":"Gamma users creating charts via API without the dataset grant; admins testing with a limited role; datasets whose access was revoked after an export/import between environments.","solutions":["Grant the user's role access to the dataset (Access requests / Security > List of Chart Roles or dataset permission) and retry.","Verify access first with GET /api/v1/dataset/<id> as the same user.","If using RLS or custom security managers, confirm raise_for_access rules actually permit this principal for this datasource."],"exampleFix":"# before (as Gamma user)\nPOST /api/v1/chart/ {\"datasource_id\": 7, \"datasource_type\": \"table\", ...}  # 403\n\n# after (admin grants access)\n# Security > Roles > Gamma > Permissions: add 'can read on Dataset (id:7)'\n# then retry the same POST","handlingStrategy":"try-catch","validationCode":"from superset import security_manager\nfrom superset.utils.core import get_datasource_by_id\n\ndef can_use_datasource(datasource_id: int, datasource_type: str) -> bool:\n    try:\n        ds = get_datasource_by_id(datasource_id, datasource_type)\n        security_manager.raise_for_access(datasource=ds)\n        return True\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    CreateChartCommand(properties).run()\nexcept ChartForbiddenError:\n    return {\"error\": \"no access to datasource; request dataset permission\"}, 403","preventionTips":["Grant dataset access to the creating role before chart creation.","Verify with GET /api/v1/dataset/<id> as the same principal first.","For custom security managers, test raise_for_access behavior for Gamma-like roles."],"tags":["chart","rbac","forbidden","security"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}