{"record":{"id":"25e1deae9a91d94d","repo":"apache/superset","slug":"annotation-parameters-are-invalid-25e1de","errorCode":null,"errorMessage":"Annotation parameters are invalid.","messagePattern":"Annotation parameters are invalid\\.","errorType":"validation","errorClass":"AnnotationInvalidError","httpStatus":422,"severity":"error","filePath":"superset/commands/annotation_layer/annotation/update.py","lineNumber":87,"sourceCode":"            # Validate short descr uniqueness on this layer\n            if not AnnotationDAO.validate_update_uniqueness(\n                layer_id,\n                short_descr,\n                annotation_id=self._model_id,\n            ):\n                exceptions.append(AnnotationUniquenessValidationError())\n        else:\n            self._properties[\"layer\"] = self._model.layer\n\n        # validate date time sanity\n        start_dttm: Optional[datetime] = self._properties.get(\"start_dttm\")\n        end_dttm: Optional[datetime] = self._properties.get(\"end_dttm\")\n\n        if start_dttm and end_dttm and end_dttm < start_dttm:\n            exceptions.append(AnnotationDatesValidationError())\n\n        if exceptions:\n            raise AnnotationInvalidError(exceptions=exceptions)\n","sourceCodeStart":69,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/annotation_layer/annotation/update.py#L69-L88","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Query for a conflicting name on the destination layer excluding this annotation id, then pick a unique short_descr.","Send both datetimes in one timezone and validate end_dttm >= start_dttm client-side.","Inspect error._exceptions for the exact field that failed before retrying."],"exampleFix":"# before\nPATCH /api/v1/annotation/42 {\"short_descr\": \"launch\"}  # another row already has it\n\n# after\nPATCH /api/v1/annotation/42 {\"short_descr\": \"launch-2026-Q1\"}","handlingStrategy":"validation","validationCode":"def update_is_safe(layer_id: int | None, new_descr: str, annotation_id: int,\n                            start, end) -> bool:\n    if layer_id is not None and not AnnotationDAO.validate_update_uniqueness(\n        layer_id, new_descr, annotation_id=annotation_id\n    ):\n        return False\n    return not (start and end and end < start)","typeGuard":null,"tryCatchPattern":"try:\n    UpdateAnnotationCommand(model_id, properties).run()\nexcept AnnotationInvalidError as ex:\n    field_errors = {e.field_name: e.messages for e in ex._exceptions}\n    return {\"errors\": field_errors}, 422","preventionTips":["Exclude the row's own id when checking name uniqueness client-side.","Normalize datetimes to UTC and validate end >= start before PATCH.","Use field-level error display from _exceptions to guide the user to the offending input."],"tags":["annotation","validation","uniqueness","update"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}