apache/superset · error · AnnotationNotFoundError

Annotation not found.

Error message

Annotation not found.

What it means

AnnotationNotFoundError raised by DeleteAnnotationCommand.validate() (delete.py:48) when AnnotationDAO.find_by_ids returns fewer models than requested ids — at least one annotation id in the DELETE payload does not exist. The delete command accepts a list (bulk delete), so a single stale id fails the whole batch; HTTP 404.

Source

Thrown at superset/commands/annotation_layer/annotation/delete.py:48

logger = logging.getLogger(__name__)


class DeleteAnnotationCommand(BaseCommand):
    def __init__(self, model_ids: list[int]):
        self._model_ids = model_ids
        self._models: Optional[list[Annotation]] = None

    @transaction(on_error=partial(on_error, reraise=AnnotationDeleteFailedError))
    def run(self) -> None:
        self.validate()
        assert self._models
        AnnotationDAO.delete(self._models)

    def validate(self) -> None:
        # Validate/populate model exists
        self._models = AnnotationDAO.find_by_ids(self._model_ids)
        if not self._models or len(self._models) != len(self._model_ids):
            raise AnnotationNotFoundError()

View on GitHub (pinned to f4587218dd)

Solutions

  1. Retry the delete with only the ids that still exist (filter via GET /api/v1/annotation/?q=(id:in:(...)) first).
  2. Make client delete actions idempotent: treat 404 on delete as success.
  3. Avoid double-submission in the UI (disable button while the request is in flight).

Example fix

# before
DeleteAnnotationCommand([1, 2, 999]).run()  # 999 already deleted -> whole batch 404s

# after
existing = AnnotationDAO.find_by_ids([1, 2, 999])
DeleteAnnotationCommand([m.id for m in existing]).run()
Defensive patterns

Strategy: validation

Validate before calling

from superset.daos.annotation_layer import AnnotationDAO

existing = AnnotationDAO.find_by_ids(model_ids)
live_ids = [m.id for m in existing]
if len(live_ids) != len(model_ids):
    model_ids = live_ids  # delete only what still exists

Try / catch

try:
    DeleteAnnotationCommand(model_ids).run()
except AnnotationNotFoundError:
    # treat as success: already deleted elsewhere
    log.info("annotations already deleted: %s", model_ids)

Prevention

When it happens

Trigger: DELETE /api/v1/annotation/ with body [1,2,999] where 999 is gone; double-submit of a delete request (second call finds nothing); deleting annotations already removed by another user/session.

Common situations: Bulk UI actions racing with another editor's deletes; retry logic re-sending an already-applied bulk delete; idempotent scripts assuming re-delete succeeds.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/77a87971043eec2d. Report an issue: GitHub.