{"record":{"id":"f0be67ce2c04b414","repo":"apache/superset","slug":"chart-not-found","errorCode":null,"errorMessage":"Chart not found.","messagePattern":"Chart not found\\.","errorType":"exception","errorClass":"ChartNotFoundError","httpStatus":404,"severity":"error","filePath":"superset/commands/chart/delete.py","lineNumber":55,"sourceCode":"logger = logging.getLogger(__name__)\n\n\nclass DeleteChartCommand(BaseCommand):\n    def __init__(self, model_ids: list[int]):\n        self._model_ids = model_ids\n        self._models: Optional[list[Slice]] = None\n\n    @transaction(on_error=partial(on_error, reraise=ChartDeleteFailedError))\n    def run(self) -> None:\n        self.validate()\n        assert self._models\n        ChartDAO.delete(self._models)\n\n    def validate(self) -> None:\n        # Validate/populate model exists\n        self._models = ChartDAO.find_by_ids(self._model_ids)\n        if not self._models or len(self._models) != len(self._model_ids):\n            raise ChartNotFoundError()\n        # Check there are no associated ReportSchedules\n        if reports := ReportScheduleDAO.find_by_chart_ids(self._model_ids):\n            report_names = [report.name for report in reports]\n            raise ChartDeleteFailedReportsExistError(\n                _(\n                    \"There are associated alerts or reports: %(report_names)s\",\n                    report_names=\",\".join(report_names),\n                )\n            )\n        # Check editorship\n        for model in self._models:\n            try:\n                security_manager.raise_for_editorship(model)\n            except SupersetSecurityException as ex:\n                raise ChartForbiddenError() from ex\n","sourceCodeStart":37,"sourceCodeEnd":71,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/chart/delete.py#L37-L71","documentation":"Raised as ChartNotFoundError by DeleteChartCommand.validate() when ChartDAO.find_by_ids does not return exactly one model per requested id. This means at least one chart id in the delete request does not exist (already deleted, wrong id, or filtered from view). Deletion of every chart in the batch is aborted before any row is touched.","triggerScenarios":"DELETE /api/v1/chart/ with a body id list containing a stale or nonexistent chart id; deleting a chart that another user/session already deleted; passing an internal integer id after charts were migrated/purged.","commonSituations":"Stale UI state listing a chart removed by someone else; scripts that cache chart ids across environments; double-submit of a delete request.","solutions":["Fetch the current list via GET /api/v1/chart/ and retry the delete with only ids that still exist.","Treat 'not found' as success in idempotent delete scripts (catch 404 and continue).","Check for trailing whitespace/type mismatches in ids passed to the API."],"exampleFix":"# before\nchart_dao_ids = [42]\nclient.delete('/api/v1/chart/', json={'ids': [42, 999]})\n\n# after: verify existence first\nexisting = client.get('/api/v1/chart/?q={\"filter\":[{\"col\":\"id\",\"opr\":\"in\",\"value\":[42,999]}]}').json()\nids = [r['id'] for r in existing['result']]\nclient.delete('/api/v1/chart/', json={'ids': ids})","handlingStrategy":"validation","validationCode":"existing = ChartDAO.find_by_ids(chart_ids)\nif not existing or len(existing) != len(chart_ids):\n    missing = set(chart_ids) - {c.id for c in existing or []}\n    raise ValueError(f'charts not found: {missing}')","typeGuard":null,"tryCatchPattern":"from superset.commands.chart.exceptions import ChartNotFoundError\ntry:\n    DeleteChartCommand(ids).run()\nexcept ChartNotFoundError:\n    pass  # treat as already-deleted (idempotent delete)","preventionTips":["Fetch live ids from GET /api/v1/chart/ immediately before batch deletes.","Make delete scripts idempotent by swallowing 404.","Avoid caching chart ids across environments or sessions."],"tags":["chart","delete","not-found","api"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}