roboflow/supervision · error · ValueError
Triggering anchors cannot be empty.
Error message
Triggering anchors cannot be empty.
What it means
LineZone's constructor validates that the triggering_anchors iterable is non-empty; an empty sequence means no keypoint could ever cross the line, so counting would silently produce zeros forever. The library prefers failing fast at construction over a useless-but-quiet tracker.
Source
Thrown at src/supervision/detection/line_zone.py:129
crossed the line. This is useful when dealing with unstable
bounding boxes or when detections may linger on the line.
"""
self.vector = Vector(start=start, end=end)
self.limits = self._calculate_region_of_interest_limits(vector=self.vector)
self.crossing_history_length = max(2, minimum_crossing_threshold + 1)
self.crossing_state_history: dict[int, deque[bool]] = defaultdict(
lambda: deque(maxlen=self.crossing_history_length)
)
# Tracks consecutive frames a tracker key has been absent; eviction
# requires crossing_history_length absent frames so that ByteTrack
# coasting gaps (single-frame detection drops) don't reset mid-crossing
# state prematurely.
self._tracker_frames_absent: dict[int, int] = {}
self._in_count_per_class: Counter[int | None] = Counter()
self._out_count_per_class: Counter[int | None] = Counter()
self.triggering_anchors = triggering_anchors
if not list(self.triggering_anchors):
raise ValueError("Triggering anchors cannot be empty.")
self.class_id_to_name: dict[int, str] = {}
@property
def in_count(self) -> int:
return sum(self._in_count_per_class.values())
@property
def out_count(self) -> int:
return sum(self._out_count_per_class.values())
@property
def in_count_per_class(self) -> dict[int | None, int]:
return dict(self._in_count_per_class)
@property
def out_count_per_class(self) -> dict[int | None, int]:
return dict(self._out_count_per_class)
View on GitHub (pinned to 7f254d9784)
Solutions
- Pass at least one anchor, most commonly sv.Position.CENTER or an index list like [0, 1] for pose keypoints.
- If anchors come from a pose config, assert the selection is non-empty before constructing LineZone.
- Default to [sv.Position.CENTER] when your detection has no keypoints.
Example fix
# before zone = sv.LineZone(start=start, end=end, triggering_anchors=[]) # after zone = sv.LineZone(start=start, end=end, triggering_anchors=[sv.Position.CENTER])
Defensive patterns
Strategy: validation
Validate before calling
anchors = [a for a in requested_anchors if a is not None]
if not anchors:
anchors = [sv.Position.CENTER]
zone = sv.LineZone(start=start, end=end, triggering_anchors=anchors) Prevention
- Compute anchor lists from a named constant, never inline filters that can empty.
- Unit-test zone construction with your production anchor configuration.
- Default to [sv.Position.CENTER] when keypoints are unavailable.
When it happens
Trigger: Constructing sv.LineZone(start=..., end=..., triggering_anchors=[]) — e.g. passing an empty list literal, an anchors selection computed from a pose model with zero keypoints, or a variable that was filtered down to nothing (like [k for k in range(17) if k in selected] with an empty selected set).
Common situations: Building triggering_anchors dynamically from a per-model keypoint list that is empty for the chosen model; refactoring from hardcoded anchors (e.g. [sv.Position.CENTER]) to computed ones; copy-paste from an example where the anchors list was deleted.
Related errors
- The keys of the images and annotations dictionaries must mat
- The magnitude of the vector cannot be zero.
- Invalid table position. Supported values are: TOP_LEFT, TOP_
- The number of line zones and their labels must match.
- Triggering anchors cannot be empty.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/445d907b7da4282b.
Report an issue: GitHub.