{"record":{"id":"2f59b72731de3023","repo":"roboflow/supervision","slug":"start-id-must-be-greater-than-self-no-id","errorCode":null,"errorMessage":"start_id must be greater than {self.NO_ID}","messagePattern":"start_id must be greater than (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/tracker/byte_tracker/utils.py","lineNumber":14,"sourceCode":"class IdCounter:\n    def __init__(self, start_id: int = 0) -> None:\n        \"\"\"\n        Initialize the ID counter.\n\n        Args:\n            start_id: The starting integer for the counter.\n\n        Raises:\n            ValueError: If start_id is less than or equal to -1.\n        \"\"\"\n        self.start_id = start_id\n        if self.start_id <= self.NO_ID:\n            raise ValueError(f\"start_id must be greater than {self.NO_ID}\")\n        self.reset()\n\n    def reset(self) -> None:\n        \"\"\"Reset the counter to the initial start_id.\"\"\"\n        self._id = self.start_id\n\n    def new_id(self) -> int:\n        \"\"\"\n        Get the current ID and increment the counter.\n\n        Returns:\n            The newly assigned ID.\n        \"\"\"\n        returned_id = self._id\n        self._id += 1\n        return returned_id\n\n    @property","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/tracker/byte_tracker/utils.py#L1-L32","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a non-negative `start_id` (default 0), or any int >= 0","Map a sentinel config value to the default before constructing: `start_id = 0 if start_id < 0 else start_id`","Validate user-supplied ids at the config boundary and report the allowed range instead of letting the tracker raise"],"exampleFix":"// before\nstart_id = args.id_offset if args.id_offset is not None else -1\ncounter = TraceletIDCounter(start_id=start_id)\n\n// after\nstart_id = args.id_offset if args.id_offset is not None else 0\ncounter = TraceletIDCounter(start_id=max(start_id, 0))","handlingStrategy":"validation","validationCode":"def safe_start_id(raw: int | None) -> int:\n    \"\"\"Map external id configs onto a valid tracker start id (>= 0).\"\"\"\n    return 0 if raw is None or raw < 0 else int(raw)","typeGuard":"def is_valid_start_id(value: int) -> bool:\n    \"\"\"Tracker ids must be >= 0; -1 is reserved as NO_ID.\"\"\"\n    return isinstance(value, int) and not isinstance(value, bool) and value >= 0","tryCatchPattern":null,"preventionTips":["Never use -1 as an 'unset' default for tracker ids; map it to 0 at the config boundary","Validate CLI/config ints with is_valid_start_id before constructing trackers"],"tags":["byte-track","tracking","validation","configuration"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}