roboflow/supervision · error · ValueError

start_id must be greater than {self.NO_ID}

Error message

start_id must be greater than {self.NO_ID}

What it means

The ByteTrack tracker's internal `TraceletIDCounter` assigns monotonically increasing track ids, reserving -1 (`NO_ID`) as the sentinel meaning 'no id'. The constructor therefore rejects any `start_id <= -1` at src/supervision/tracker/byte_tracker/utils.py:14. This prevents a counter from ever issuing ids that collide with the sentinel used throughout the tracker.

Source

Thrown at src/supervision/tracker/byte_tracker/utils.py:14

class IdCounter:
    def __init__(self, start_id: int = 0) -> None:
        """
        Initialize the ID counter.

        Args:
            start_id: The starting integer for the counter.

        Raises:
            ValueError: If start_id is less than or equal to -1.
        """
        self.start_id = start_id
        if self.start_id <= self.NO_ID:
            raise ValueError(f"start_id must be greater than {self.NO_ID}")
        self.reset()

    def reset(self) -> None:
        """Reset the counter to the initial start_id."""
        self._id = self.start_id

    def new_id(self) -> int:
        """
        Get the current ID and increment the counter.

        Returns:
            The newly assigned ID.
        """
        returned_id = self._id
        self._id += 1
        return returned_id

    @property

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Use a non-negative `start_id` (default 0), or any int >= 0
  2. Map a sentinel config value to the default before constructing: `start_id = 0 if start_id < 0 else start_id`
  3. Validate user-supplied ids at the config boundary and report the allowed range instead of letting the tracker raise

Example fix

// before
start_id = args.id_offset if args.id_offset is not None else -1
counter = TraceletIDCounter(start_id=start_id)

// after
start_id = args.id_offset if args.id_offset is not None else 0
counter = TraceletIDCounter(start_id=max(start_id, 0))
Defensive patterns

Strategy: validation

Validate before calling

def safe_start_id(raw: int | None) -> int:
    """Map external id configs onto a valid tracker start id (>= 0)."""
    return 0 if raw is None or raw < 0 else int(raw)

Type guard

def is_valid_start_id(value: int) -> bool:
    """Tracker ids must be >= 0; -1 is reserved as NO_ID."""
    return isinstance(value, int) and not isinstance(value, bool) and value >= 0

Prevention

When it happens

Trigger: Constructing the id counter (directly or via a tracker wrapper that forwards `start_id`) with `start_id=-1` or any value below it, e.g. when trying to make ids line up with 0-based or -1-based external ids, or when passing an unvalidated CLI/config value straight through.

Common situations: Reading `start_id` from a config file or CLI argument where -1 is the conventional 'unset' marker and forwarding it without mapping; porting code from another tracker that allowed -1; arithmetic on a user-supplied offset producing a negative start.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/2f59b72731de3023. Report an issue: GitHub.