roboflow/supervision · error · ValueError
Triggering anchors cannot be empty.
Error message
Triggering anchors cannot be empty.
What it means
Raised by PolygonZone.__init__ when triggering_anchors materializes to an empty list. The zone decides in/out membership purely by testing the configured anchor points of each box; with zero anchors there is no predicate to evaluate, so construction fails fast rather than silently matching nothing.
Source
Thrown at src/supervision/detection/tools/polygon_zone.py:85
... )
>>> detections = sv.Detections(xyxy=np.array([[80, 80, 120, 120]]))
>>> polygon_zone.trigger(detections)
array([ True])
```
"""
def __init__(
self,
polygon: npt.NDArray[np.int64],
triggering_anchors: Iterable[Position] = (Position.BOTTOM_CENTER,),
require_all_anchors: bool = True,
) -> None:
self.polygon = polygon.astype(int)
# Materialize once so we can safely accept generators without exhausting them.
self.triggering_anchors = list(triggering_anchors)
if not self.triggering_anchors:
raise ValueError("Triggering anchors cannot be empty.")
self.require_all_anchors = require_all_anchors
self.current_count = 0
x_max, y_max = np.max(polygon, axis=0)
self.mask = polygon_to_mask(
polygon=polygon, resolution_wh=(x_max + 2, y_max + 2)
)
def trigger(self, detections: Detections) -> npt.NDArray[np.bool_]:
"""
Determines if the detections are within the polygon zone.
Anchor points are calculated from original (unclipped) detection boxes to
avoid per-zone clipping shifting anchor positions. This prevents a single
detection from being counted in multiple non-overlapping zones due to
clipping artifacts, although overlapping zones may still legitimately
contain the same detection.View on GitHub (pinned to 7f254d9784)
Solutions
- Pass at least one anchor, the typical default being triggering_anchors=[Position.BOTTOM_CENTER].
- Validate the config source before constructing the zone: raise a clear config error when the anchors field is empty.
- If the emptiness is legitimate in your flow (zone disabled), skip constructing the PolygonZone entirely.
Example fix
# before zone = sv.PolygonZone(polygon=polygon, triggering_anchors=[]) # after zone = sv.PolygonZone(polygon=polygon, triggering_anchors=[sv.Position.BOTTOM_CENTER])
Defensive patterns
Strategy: validation
Validate before calling
anchors = list(triggering_anchors) or [sv.Position.BOTTOM_CENTER]
if not anchors:
raise ValueError('config error: triggering_anchors is empty')
zone = sv.PolygonZone(polygon=polygon, triggering_anchors=anchors) Type guard
def has_triggering_anchor(items) -> bool:
return bool(list(items)) Prevention
- Validate zone config (polygon and anchors) at load time, before the processing loop starts.
- Default empty config to [Position.BOTTOM_CENTER] rather than [] in your own config layer.
When it happens
Trigger: Passing triggering_anchors=[] to PolygonZone; passing a generator that is already exhausted; building the anchor list programmatically (e.g. from CLI flags or a config filter) that ends up empty.
Common situations: Config-driven applications where an anchor list comes from a YAML/JSON file and the user leaves it empty or filters out all entries; refactoring that accidentally passes an empty tuple default.
Related errors
- module {__name__} has no attribute {name}
- Edge indices must use the 1-based convention and be within t
- sigma must contain at least one value
- All sigma values must be positive
- max_axis must be positive when provided
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/85f8e9751f32376c.
Report an issue: GitHub.