apache/superset · error · AnnotationInvalidError

Annotation parameters are invalid.

Error message

Annotation parameters are invalid.

What it means

AnnotationInvalidError (422) raised at the end of UpdateAnnotationCommand.validate() (update.py:87). As with create, it aggregates field ValidationErrors: uniqueness of short_descr on the target layer (checked with annotation_id excluded so the row's own name is allowed) and start/end datetime sanity. Raised only when at least one of those checks failed.

Source

Thrown at superset/commands/annotation_layer/annotation/update.py:87

            # 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 sanity
        start_dttm: Optional[datetime] = self._properties.get("start_dttm")
        end_dttm: Optional[datetime] = self._properties.get("end_dttm")

        if start_dttm and end_dttm and end_dttm < start_dttm:
            exceptions.append(AnnotationDatesValidationError())

        if exceptions:
            raise AnnotationInvalidError(exceptions=exceptions)

View on GitHub (pinned to f4587218dd)

Solutions

  1. Query for a conflicting name on the destination layer excluding this annotation id, then pick a unique short_descr.
  2. Send both datetimes in one timezone and validate end_dttm >= start_dttm client-side.
  3. Inspect error._exceptions for the exact field that failed before retrying.

Example fix

# before
PATCH /api/v1/annotation/42 {"short_descr": "launch"}  # another row already has it

# after
PATCH /api/v1/annotation/42 {"short_descr": "launch-2026-Q1"}
Defensive patterns

Strategy: validation

Validate before calling

def update_is_safe(layer_id: int | None, new_descr: str, annotation_id: int,
                            start, end) -> bool:
    if layer_id is not None and not AnnotationDAO.validate_update_uniqueness(
        layer_id, new_descr, annotation_id=annotation_id
    ):
        return False
    return not (start and end and end < start)

Try / catch

try:
    UpdateAnnotationCommand(model_id, properties).run()
except AnnotationInvalidError as ex:
    field_errors = {e.field_name: e.messages for e in ex._exceptions}
    return {"errors": field_errors}, 422

Prevention

When it happens

Trigger: PATCH /api/v1/annotation/<id> renaming it to a short_descr that another annotation on the same (possibly new) layer already uses; or setting end_dttm earlier than start_dttm; renaming plus moving layers where the target layer already has that description.

Common situations: Copy-paste of descriptions between annotations on one layer; timezone-naive vs aware datetime strings comparing unexpectedly; renaming during a layer move colliding with existing entries.

Related errors


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