apache/superset · error · AnnotationLayerNotFoundError
Annotation layer not found.
Error message
Annotation layer not found.
What it means
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.
Source
Thrown at superset/commands/annotation_layer/annotation/create.py:57
class CreateAnnotationCommand(BaseCommand):
def __init__(self, data: dict[str, Any]):
self._properties = data.copy()
@transaction(on_error=partial(on_error, reraise=AnnotationCreateFailedError))
def run(self) -> Model:
self.validate()
return AnnotationDAO.create(attributes=self._properties)
def validate(self) -> None:
exceptions: list[ValidationError] = []
layer_id: Optional[int] = self._properties.get("layer")
start_dttm: Optional[datetime] = self._properties.get("start_dttm")
end_dttm: Optional[datetime] = self._properties.get("end_dttm")
short_descr = self._properties.get("short_descr", "")
# 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
- 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.
Example fix
# before
POST /api/v1/annotation/
{"short_descr": "launch", "start_dttm": "2026-01-01T00:0000", "end_dttm": "2026-01-02T00:00:00"}
# after
POST /api/v1/annotation/
{"layer": 1, "short_descr": "launch", "start_dttm": "2026-01-01T00:00:00", "end_dttm": "2026-01-02T00:00:00"} Defensive patterns
Strategy: validation
Validate before calling
def valid_annotation_layer_ref(payload: dict) -> bool:
layer = payload.get("layer")
return isinstance(layer, int) and not isinstance(layer, bool) and layer > 0
if not valid_annotation_layer_ref(payload):
raise RequestValidationError("'layer' must be a positive integer annotation layer id") Type guard
def has_int_layer(payload: dict) -> TypeGuard[dict]:
return isinstance(payload.get("layer"), int) Try / catch
try:
CreateAnnotationCommand(properties).run()
except AnnotationLayerNotFoundError:
return {"error": "annotation layer missing or unknown"}, 404 Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Dashboard %(dashboard_id)s not found
- Annotation parameters are invalid.
- Annotation not found.
- Annotation not found.
- Annotation layer not found.
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/931329fe1a576e62.
Report an issue: GitHub.