{"record":{"id":"ac942aba07b0d250","repo":"commaai/openpilot","slug":"no-camera-file-for-segment-seg-idx","errorCode":null,"errorMessage":"No camera file for segment {seg_idx}","messagePattern":"No camera file for segment (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"openpilot/tools/clip/run.py","lineNumber":152,"sourceCode":"  probe = ffprobe(camera_path)\n  stream = probe[\"streams\"][0]\n  return stream[\"width\"], stream[\"height\"]\n\n\ndef iter_segment_frames(camera_paths, start_time, end_time, fps=20, use_qcam=False, frame_size: tuple[int, int] | None = None):\n  frames_per_seg = fps * 60\n  start_frame, end_frame = int(start_time * fps), int(end_time * fps)\n  current_seg: int = -1\n  get_frame: Callable[[int], np.ndarray] | None = None\n\n  for global_idx in range(start_frame, end_frame):\n    seg_idx, local_idx = global_idx // frames_per_seg, global_idx % frames_per_seg\n\n    if seg_idx != current_seg:\n      current_seg = seg_idx\n      path = camera_paths[seg_idx] if seg_idx < len(camera_paths) else None\n      if not path:\n        raise RuntimeError(f\"No camera file for segment {seg_idx}\")\n\n      if use_qcam:\n        w, h = frame_size or get_frame_dimensions(path)\n        with FileReader(path) as f:\n          result = subprocess.run([\"ffmpeg\", \"-v\", \"quiet\", \"-i\", \"-\", \"-f\", \"rawvideo\", \"-pix_fmt\", \"nv12\", \"-\"],\n                                  input=f.read(), capture_output=True)\n        if result.returncode != 0:\n          raise RuntimeError(f\"ffmpeg failed: {result.stderr.decode()}\")\n        seg_frames = np.frombuffer(result.stdout, dtype=np.uint8).reshape(-1, w * h * 3 // 2)\n        get_frame = seg_frames.__getitem__\n      else:\n        get_frame = FrameReader(path, pix_fmt=\"nv12\").get\n\n    assert get_frame is not None\n    yield global_idx, get_frame(local_idx)\n\n\nclass FrameQueue:","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/clip/run.py#L134-L170","documentation":"iter_segment_frames() in the clip tool maps global frame indices to route segments (frames_per_seg = fps * 60). When it moves to a new segment whose camera path is missing (index beyond camera_paths or an empty/None entry), it raises instead of skipping. This means the requested start_time/end_time window reaches segments that have no camera file (e.g. qcamera.ts) available.","triggerScenarios":"Clipping a time range whose end crosses into a segment index with no camera file listed; camera_paths built from an rlog/segment list where some segments lack qcameras; passing camera_paths shorter than the number of segments spanned by start_time..end_time.","commonSituations":"Route partially uploaded (later segments missing qcamera.ts); off-by-one in end_time (one second past the last segment); mixing 20fps assumption with a route recorded at a different fps so segment math overshoots.","solutions":["Clamp end_time to the last segment that actually has a camera file: end_time = min(end_time, len(camera_paths_with_files) * 60)","Filter camera_paths to only existing files and confirm the count covers the requested window before starting","Pass the fps matching the route (default 20) so segment boundary math matches reality"],"exampleFix":"# before\nend_time = 125.0  # route only has 2 segments (120s) with camera files\n\n# after\nn_segs = sum(1 for p in camera_paths if p)\nend_time = min(end_time, n_segs * 60.0)","handlingStrategy":"validation","validationCode":"last_valid = max(i for i, p in enumerate(camera_paths) if p)\nmax_time = (last_valid + 1) * 60.0\nassert end_time <= max_time, f\"end_time {end_time}s exceeds last camera segment at {max_time}s\"","typeGuard":null,"tryCatchPattern":"try:\n    yield from iter_segment_frames(camera_paths, start_time, end_time, fps)\nexcept RuntimeError as e:\n    if 'No camera file' in str(e):\n        seg = int(str(e).rsplit(' ', 1)[-1])\n        raise SystemExit(f\"trim clip to segment {seg - 1}: window reaches missing camera data\")\n    raise","preventionTips":["Compute the number of camera-backed segments from camera_paths and clamp start/end times to that span before generating","Pass the route's true fps so the frames_per_seg = fps*60 segment math matches the recorded data"],"tags":["route-data","clip-tool","segments","validation","openpilot"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}