{"record":{"id":"f32f14fa39e823f8","repo":"AtsushiSakai/PythonRobotics","slug":"agent-index-cannot-be-0","errorCode":null,"errorMessage":"Agent index cannot be 0","messagePattern":"Agent index cannot be 0","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"PathPlanning/TimeBasedPathPlanning/GridWithDynamicObstacles.py","lineNumber":299,"sourceCode":"        if zero_mask[-1]:  # If the last element is zero, add the last index to end_indices\n            end_indices = np.append(end_indices, len(vals) - 1)\n\n        # Create pairs of (first zero, last zero)\n        intervals = [Interval(int(start), int(end)) for start, end in zip(start_indices, end_indices)]\n\n        # Remove intervals where a cell is only free for one time step. Those intervals not provide enough time to\n        # move into and out of the cell each take 1 time step, and the cell is considered occupied during\n        # both the time step when it is entering the cell,  and the time step when it is leaving the cell.\n        intervals = [interval for interval in intervals if interval.start_time != interval.end_time]\n        return intervals\n    \n    \"\"\"\n    Reserve an agent's path in the grid. Raises an exception if the agent's index is 0, or if a position is\n    already reserved by a different agent.\n    \"\"\"\n    def reserve_path(self, node_path: NodePath, agent_index: int):\n        if agent_index == 0:\n            raise Exception(\"Agent index cannot be 0\")\n        \n        for i, node in enumerate(node_path.path):\n            reservation_finish_time = node.time + 1\n            if i < len(node_path.path) - 1:\n                reservation_finish_time = node_path.path[i + 1].time\n\n            self.reserve_position(node.position, agent_index, Interval(node.time, reservation_finish_time))\n\n    \"\"\"\n    Reserve a position for the provided agent during the provided time interval.\n    Raises an exception if the agent's index is 0, or if the position is already reserved by a different agent during the interval.\n    \"\"\"\n    def reserve_position(self, position: Position, agent_index: int, interval: Interval):\n        if agent_index == 0:\n            raise Exception(\"Agent index cannot be 0\")\n\n        for t in range(interval.start_time, interval.end_time + 1):\n            current_reserver = self.reservation_matrix[position.x, position.y, t]","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/AtsushiSakai/PythonRobotics/blob/1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d/PathPlanning/TimeBasedPathPlanning/GridWithDynamicObstacles.py#L281-L317","documentation":"Raised by reserve_path when agent_index is 0. Index 0 is the sentinel stored in reservation_matrix to mean 'unreserved', so it cannot be used as a real agent identifier. Agents are expected to be numbered starting from 1.","triggerScenarios":"Calling grid.reserve_path(node_path, agent_index=0) directly, or via plan(...) passing an agent index of 0 (e.g. iterating agents from a 0-based loop without adding 1).","commonSituations":"Using a 0-based loop `for i in range(num_agents): plan(path, i)` instead of 1-based indexing; off-by-one errors after refactoring agent IDs; passing a default value of 0 for agent_index.","solutions":["Change the call to use agent_index >= 1 (e.g. use i + 1 in a 0-based loop)","Audit agent ID assignment so agents are numbered 1..N throughout the codebase"],"exampleFix":"# before\nfor i in range(len(paths)):\n    grid.reserve_path(paths[i], i)\n\n# after\nfor i in range(len(paths)):\n    grid.reserve_path(paths[i], i + 1)","handlingStrategy":"validation","validationCode":"assert agent_index >= 1, \"agent_index must be >= 1 (0 is the unreserved sentinel)\"","typeGuard":"def is_valid_agent_index(idx: int) -> bool:\n    return isinstance(idx, int) and idx >= 1","tryCatchPattern":null,"preventionTips":["Use 1-based agent IDs everywhere; reserve 0 as the 'unreserved' sentinel","Wrap agent loops: for i in range(1, num_agents + 1)"],"tags":["path-planning","reservation","agent-index","off-by-one"],"backgroundTag":"reserved-sentinel-value-misuse","analyzedSha":"1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d","analyzedAt":"2026-08-28T13:23:33.733Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}