{"record":{"id":"6632b59f9dc788d7","repo":"apache/superset","slug":"changing-one-or-more-of-these-dashboards-is-forbid","errorCode":null,"errorMessage":"Changing one or more of these dashboards is forbidden","messagePattern":"Changing one or more of these dashboards is forbidden","errorType":"exception","errorClass":"DashboardsForbiddenError","httpStatus":403,"severity":"error","filePath":"superset/commands/chart/create.py","lineNumber":88,"sourceCode":"        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":70,"sourceCodeEnd":95,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/chart/create.py#L70-L95","documentation":"DashboardsForbiddenError (ForbiddenError, 403) raised in ChartCreateCommand.validate() when, for any dashboard id in the payload, security_manager.is_editor(dash) is false — the user may see the dashboard but cannot edit (add charts to) it. The dashboard list itself was resolved successfully, so this is purely an ownership/role check, and it aborts immediately (not aggregated into the 422 list).","triggerScenarios":"POST /api/v1/chart/ with \"dashboards\": [id] where the user lacks editor rights (not owner, no 'can write on Dashboard' grant); Gamma user targeting an admin-owned dashboard.","commonSituations":"Automated chart creation attaching to shared dashboards without prior ownership transfer; role missing dashboard-write permission; dashboards owned by a service account.","solutions":["Have the dashboard owner add the user as an editor (dashboard > ... > Manage > Editors) or grant the role 'can write on Dashboard'.","Create the chart without the 'dashboards' field, then ask an editor to import/move it onto the dashboard.","Take ownership via the dashboard's Save-as / ownership transfer if permitted."],"exampleFix":"# before\nPOST /api/v1/chart/ {\"datasource_id\": 7, \"datasource_type\": \"table\", \"dashboards\": [3], ...}\n\n# after\nPOST /api/v1/chart/ {\"datasource_id\": 7, \"datasource_type\": \"table\", ...}  # create standalone\n# then an editor adds it to dashboard 3 from the dashboard UI","handlingStrategy":"validation","validationCode":"from superset import security_manager\nfrom superset.daos.dashboard import DashboardDAO\n\ndashboards = DashboardDAO.find_by_ids(dashboard_ids)\neditable = all(security_manager.is_editor(d) for d in dashboards) if dashboards else True\nif not editable:\n    payload.pop(\"dashboards\", None)  # create standalone chart instead","typeGuard":null,"tryCatchPattern":"try:\n    CreateChartCommand(properties).run()\nexcept DashboardsForbiddenError:\n    payload.pop(\"dashboards\", None)\n    chart = CreateChartCommand(payload).run()  # standalone; editor adds it later","preventionTips":["Have owners add the API user as a dashboard editor before scripted chart creation.","When in doubt, create charts without 'dashboards' and attach later from an authorized session.","Check is_editor semantics for your security manager before automating dashboard writes."],"tags":["chart","dashboard","rbac","forbidden"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}