apache/superset · error · AnnotationInvalidError

Annotation parameters are invalid.

Error message

Annotation parameters are invalid.

What it means

AnnotationInvalidError (CommandInvalidError, HTTP 422) raised at the end of AnnotationCreateCommand.validate() when the per-field validation list is non-empty. Two checks feed the list: AnnotationUniquenessValidationError (short_descr already used on that layer) and AnnotationDatesValidationError (end_dttm earlier than start_dttm). The raised error carries the list of Marshmallow ValidationErrors in _exceptions so the API can return field-level details.

Source

Thrown at superset/commands/annotation_layer/annotation/create.py:72

        # Validate/populate model exists
        if not layer_id and not isinstance(layer_id, int):
            raise AnnotationLayerNotFoundError()
        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):
            exceptions.append(AnnotationUniquenessValidationError())

        # validate date time sanity
        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. Check uniqueness first: GET /api/v1/annotation/?q=(layer:<id>,short_descr:eq:<value>) and reuse or rename.
  2. Normalize start_dttm/end_dttm to the same timezone (UTC) and assert end >= start before sending.
  3. Read error._exceptions for field-level messages to know which validation failed.

Example fix

# before
{"layer": 1, "short_descr": "launch", "start_dttm": "2026-03-02T00:00:00Z", "end_dttm": "2026-03-01T00:00:00Z"}

# after
{"layer": 1, "short_descr": "launch-2", "start_dttm": "2026-03-01T00:00:00Z", "end_dttm": "2026-03-02T00:00:00Z"}
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime

def annotation_valid(layer_id: int, short_descr: str, start: datetime, end: datetime) -> bool:
    unique = AnnotationDAO.validate_update_uniqueness(layer_id, short_descr)
    dates_ok = not (start and end and end < start)
    return unique and dates_ok

Try / catch

try:
    CreateAnnotationCommand(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: POST /api/v1/annotation/ with a short_descr that already exists on the target layer; or with end_dttm < start_dttm (e.g. timezone mix-up flipping the order); both problems at once produce two nested exceptions.

Common situations: Duplicate 'launch'/'deploy' markers on the same layer; ISO strings with and without timezone offsets parsed into datetimes whose comparison surprises the author; replaying an import script twice creating the second copy.

Related errors


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