{"record":{"id":"3b849cc354dfd45a","repo":"apache/superset","slug":"css-template-not-found","errorCode":null,"errorMessage":"CSS template not found.","messagePattern":"CSS template not found\\.","errorType":"exception","errorClass":"CssTemplateNotFoundError","httpStatus":500,"severity":"warning","filePath":"superset/commands/css/delete.py","lineNumber":48,"sourceCode":"logger = logging.getLogger(__name__)\n\n\nclass DeleteCssTemplateCommand(BaseCommand):\n    def __init__(self, model_ids: list[int]):\n        self._model_ids = model_ids\n        self._models: Optional[list[CssTemplate]] = None\n\n    @transaction(on_error=partial(on_error, reraise=CssTemplateDeleteFailedError))\n    def run(self) -> None:\n        self.validate()\n        assert self._models\n        CssTemplateDAO.delete(self._models)\n\n    def validate(self) -> None:\n        # Validate/populate model exists\n        self._models = CssTemplateDAO.find_by_ids(self._model_ids)\n        if not self._models or len(self._models) != len(self._model_ids):\n            raise CssTemplateNotFoundError()\n","sourceCodeStart":30,"sourceCodeEnd":49,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/css/delete.py#L30-L49","documentation":"CssTemplateNotFoundError is raised by CssTemplateDeleteCommand.validate() when CssTemplateDAO.find_by_ids() returns no rows, or returns fewer rows than the number of requested ids. It signals that one or more CSS template ids in the delete request do not exist in the metadata database.","triggerScenarios":"Calling DELETE /api/v1/css_template/ with a list of ids where at least one id is missing, already deleted, or a client-side stale id from a previous session. Also triggered when a concurrent request deletes the same template between the client's fetch and delete.","commonSituations":"UI grid with multi-select where a template was deleted by another user in another tab; scripts deleting by hardcoded ids after a DB reset; double-click on the delete button causing the second request to 404.","solutions":["Refresh the CSS template list (GET /api/v1/css_template/) and retry the delete with only ids that still exist.","Make the delete flow idempotent in the client: treat a 404 CssTemplateNotFoundError as success when the goal is removal.","Check for concurrent deletion: confirm no other admin/session removed the templates before issuing the bulk delete."],"exampleFix":"# before\n CssTemplateDeleteCommand([1, 2, 99]).run()  # 99 no longer exists\n\n# after\nexisting = CssTemplateDAO.find_by_ids([1, 2, 99])\nCssTemplateDeleteCommand([t.id for t in existing]).run()","handlingStrategy":"validation","validationCode":"from superset.daos.css_templates import CssTemplateDAO\n\nids = [1, 2, 99]\nexisting = CssTemplateDAO.find_by_ids(ids)\nif len(existing) != len(ids):\n    missing = set(ids) - {t.id for t in existing}\n    logger.info('skipping already-deleted css templates: %s', missing)\nids_to_delete = [t.id for t in existing]","typeGuard":null,"tryCatchPattern":"try:\n    CssTemplateDeleteCommand(ids).run()\nexcept CssTemplateNotFoundError:\n    # idempotent delete: target state already reached\n    pass","preventionTips":["Refresh id lists from the API immediately before bulk deletes.","Make UI delete buttons idempotent for 404 responses.","Avoid hardcoded CSS template ids in scripts."],"tags":["css-template","delete","not-found","dao"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}