apache/superset · error · AnnotationNotFoundError
Annotation not found.
Error message
Annotation not found.
What it means
AnnotationNotFoundError from UpdateAnnotationCommand.validate() (update.py:61): AnnotationDAO.find_by_id(self._model_id) returned None, so the annotation being PATCHed no longer exists. HTTP 404. The command is instantiated with a model id from the URL, so this means the target itself is gone, not a related object.
Source
Thrown at superset/commands/annotation_layer/annotation/update.py:61
self._model_id = model_id
self._properties = data.copy()
self._model: Optional[Annotation] = None
@transaction(on_error=partial(on_error, reraise=AnnotationUpdateFailedError))
def run(self) -> Model:
self.validate()
assert self._model
return AnnotationDAO.update(self._model, self._properties)
def validate(self) -> None:
exceptions: list[ValidationError] = []
layer_id: Optional[int] = self._properties.get("layer")
short_descr: str = self._properties.get("short_descr", "")
# Validate/populate model exists
self._model = AnnotationDAO.find_by_id(self._model_id)
if not self._model:
raise AnnotationNotFoundError()
# Validate/populate layer exists
if layer_id:
annotation_layer = AnnotationLayerDAO.find_by_id(layer_id)
if not annotation_layer:
raise AnnotationLayerNotFoundError()
self._properties["layer"] = annotation_layer
# Validate short descr uniqueness on this layer
if not AnnotationDAO.validate_update_uniqueness(
layer_id,
short_descr,
annotation_id=self._model_id,
):
exceptions.append(AnnotationUniquenessValidationError())
else:
self._properties["layer"] = self._model.layer
# validate date time sanityView on GitHub (pinned to f4587218dd)
Solutions
- GET /api/v1/annotation/<id> first; if 404, remove the row from the client list instead of patching.
- Refresh the annotation list after concurrent deletes and reapply the edit to a live row.
- In scripts, guard updates with an existence check and treat 404 as a no-op.
Example fix
# before
UpdateAnnotationCommand(model_id=42, properties).run()
# after
from superset.daos.annotation_layer import AnnotationDAO
if AnnotationDAO.find_by_id(42) is None:
log.info("annotation 42 gone; skipping update")
else:
UpdateAnnotationCommand(model_id=42, properties).run() Defensive patterns
Strategy: validation
Validate before calling
from superset.daos.annotation_layer import AnnotationDAO
if AnnotationDAO.find_by_id(annotation_id) is None:
remove_from_client_list(annotation_id); return # skip update Try / catch
try:
UpdateAnnotationCommand(model_id, properties).run()
except AnnotationNotFoundError:
refresh_annotation_list(); notify_user("annotation was deleted by another session") Prevention
- Verify the annotation still exists (GET) before showing an edit form save action.
- Refresh lists after concurrent-editing sessions; lock or notify on concurrent deletes.
- In scripts, make PATCH guarded by existence checks and idempotent.
When it happens
Trigger: PATCH /api/v1/annotation/<id> after that annotation was deleted in another tab/session; editing from a stale list view; replaying an update request against a different metadata DB.
Common situations: Two users editing the same annotation layer simultaneously; long-open editor pages whose row was removed; environment mismatch in scripted updates.
Related errors
- Annotation layer not found.
- Annotation layer not found.
- Annotation not found.
- Annotation parameters are invalid.
- Annotation layer not found.
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/8691c9d064f5575d.
Report an issue: GitHub.