roboflow/supervision · error · ValueError
The number of line zones and their labels must match.
Error message
The number of line zones and their labels must match.
What it means
LineZoneAnnotator.annotate(frame, line_zones, line_zone_labels) requires one label per line zone; when explicit labels are provided their count must equal len(line_zones). Labels are zipped with zones to render per-zone crossing counts, so a mismatch means ambiguous output and is rejected.
Source
Thrown at src/supervision/detection/line_zone.py:831
line_zone_labels: list[str] | None = None,
) -> npt.NDArray[np.uint8]:
"""
Draws a table with the number of objects of each class that crossed each line.
Args:
frame: The image on which the table will be drawn.
line_zones: The line zones to be annotated.
line_zone_labels: The labels, one for each line zone. If not
provided, the default labels will be used.
Returns:
The image with the table drawn on it.
"""
if line_zone_labels is None:
line_zone_labels = [f"Line {i + 1}:" for i in range(len(line_zones))]
if len(line_zones) != len(line_zone_labels):
raise ValueError("The number of line zones and their labels must match.")
text_lines = ["Line Crossings:"]
for line_zone, line_zone_label in zip(line_zones, line_zone_labels):
text_lines.append(line_zone_label)
class_id_to_name = line_zone.class_id_to_name
for direction, count_per_class in [
("In", line_zone.in_count_per_class),
("Out", line_zone.out_count_per_class),
]:
if not count_per_class:
continue
text_lines.append(f" {direction}:")
for class_id, count in count_per_class.items():
if self.force_draw_class_ids:
class_name = str(class_id)
elif class_id is None:View on GitHub (pinned to 7f254d9784)
Solutions
- Build labels from the zones themselves: line_zone_labels=[f'Zone {i+1}' for i in range(len(zones))] or omit them to get defaults.
- Keep zones and labels in the same config block so they cannot diverge.
- Add an assert len(line_zones) == len(labels) near where either is defined.
Example fix
# before
annotator.annotate(
frame=frame,
line_zones=zones, # 3 zones
line_zone_labels=["In", "Out"], # 2 labels
)
# after
annotator.annotate(
frame=frame,
line_zones=zones,
line_zone_labels=[f"Zone {i + 1}" for i in range(len(zones))],
) Defensive patterns
Strategy: validation
Validate before calling
if line_zone_labels is not None:
assert len(line_zones) == len(line_zone_labels), (
f"{len(line_zones)} zones vs {len(line_zone_labels)} labels"
)
annotator.annotate(frame=frame, line_zones=line_zones, line_zone_labels=line_zone_labels) Prevention
- Derive labels from zones: [f'Zone {i+1}' for i in range(len(zones))].
- Keep zones and labels in the same config block.
- Omit labels entirely to get defaults when custom text is not needed.
When it happens
Trigger: Passing 3 zones with 2 labels (e.g. reusing a hardcoded label list after adding a zone), or a label list generated from a different config section than the zones (['Entrance', 'Exit'] vs 4 configured zones).
Common situations: Zones defined in a config file and labels hardcoded in code, drifting out of sync; iterating a subset of zones but not the labels; adding a new zone during a demo without updating labels.
Related errors
- Invalid table position. Supported values are: TOP_LEFT, TOP_
- Triggering anchors cannot be empty.
- The magnitude of the vector cannot be zero.
- module {__name__} has no attribute {name}
- Edge indices must use the 1-based convention and be within t
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/1313959d9ac5427d.
Report an issue: GitHub.