{"record":{"id":"931329fe1a576e62","repo":"apache/superset","slug":"annotation-layer-not-found","errorCode":null,"errorMessage":"Annotation layer not found.","messagePattern":"Annotation layer not found\\.","errorType":"exception","errorClass":"AnnotationLayerNotFoundError","httpStatus":400,"severity":"error","filePath":"superset/commands/annotation_layer/annotation/create.py","lineNumber":57,"sourceCode":"class CreateAnnotationCommand(BaseCommand):\n    def __init__(self, data: dict[str, Any]):\n        self._properties = data.copy()\n\n    @transaction(on_error=partial(on_error, reraise=AnnotationCreateFailedError))\n    def run(self) -> Model:\n        self.validate()\n        return AnnotationDAO.create(attributes=self._properties)\n\n    def validate(self) -> None:\n        exceptions: list[ValidationError] = []\n        layer_id: Optional[int] = self._properties.get(\"layer\")\n        start_dttm: Optional[datetime] = self._properties.get(\"start_dttm\")\n        end_dttm: Optional[datetime] = self._properties.get(\"end_dttm\")\n        short_descr = self._properties.get(\"short_descr\", \"\")\n\n        # Validate/populate model exists\n        if not layer_id and not isinstance(layer_id, int):\n            raise AnnotationLayerNotFoundError()\n        annotation_layer = AnnotationLayerDAO.find_by_id(layer_id)\n        if not annotation_layer:\n            raise AnnotationLayerNotFoundError()\n        self._properties[\"layer\"] = annotation_layer\n\n        # Validate short descr uniqueness on this layer\n        if not AnnotationDAO.validate_update_uniqueness(layer_id, short_descr):\n            exceptions.append(AnnotationUniquenessValidationError())\n\n        # validate date time sanity\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":39,"sourceCodeEnd":73,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/annotation_layer/annotation/create.py#L39-L73","documentation":"Raised by AnnotationCreateCommand.validate() (create.py:57) when the 'layer' property is missing/falsy or not an integer, i.e. the request did not reference an annotation layer id at all. AnnotationLayerNotFoundError (a CommandException) normally maps to 404 in the REST layer. It fires before the DAO lookup, so the layer id never even hits the database.","triggerScenarios":"POST /api/v1/annotation/ with a body omitting 'layer' or setting it to null/'' /a non-int value; programmatic creation from a form where the layer selector was left empty.","commonSituations":"Frontend form submits before the user picks a layer; API clients modeled on annotation layer endpoints that assume layer is optional; marshmallow schema coercion differences turning a valid id into a string.","solutions":["Include an integer 'layer' field (the annotation layer id) in the POST /api/v1/annotation/ payload.","Fetch valid layer ids first with GET /api/v1/annotation_layer/ and populate a required selector in the UI.","Validate the payload client-side before submit so layer is always a positive integer."],"exampleFix":"# before\nPOST /api/v1/annotation/\n{\"short_descr\": \"launch\", \"start_dttm\": \"2026-01-01T00:0000\", \"end_dttm\": \"2026-01-02T00:00:00\"}\n\n# after\nPOST /api/v1/annotation/\n{\"layer\": 1, \"short_descr\": \"launch\", \"start_dttm\": \"2026-01-01T00:00:00\", \"end_dttm\": \"2026-01-02T00:00:00\"}","handlingStrategy":"validation","validationCode":"def valid_annotation_layer_ref(payload: dict) -> bool:\n    layer = payload.get(\"layer\")\n    return isinstance(layer, int) and not isinstance(layer, bool) and layer > 0\n\nif not valid_annotation_layer_ref(payload):\n    raise RequestValidationError(\"'layer' must be a positive integer annotation layer id\")","typeGuard":"def has_int_layer(payload: dict) -> TypeGuard[dict]:\n    return isinstance(payload.get(\"layer\"), int)","tryCatchPattern":"try:\n    CreateAnnotationCommand(properties).run()\nexcept AnnotationLayerNotFoundError:\n    return {\"error\": \"annotation layer missing or unknown\"}, 404","preventionTips":["Make the layer selector required in any annotation form before enabling submit.","Validate the payload schema client-side: layer present, integer, positive.","Load layer options from GET /api/v1/annotation_layer/ so only real ids can be sent."],"tags":["annotation","validation","not-found","api"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}