{"record":{"id":"540876ee5b4cb2c2","repo":"roboflow/supervision","slug":"requested-frames-are-outbound","errorCode":null,"errorMessage":"Requested frames are outbound","messagePattern":"Requested frames are outbound","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/supervision/utils/video.py","lineNumber":178,"sourceCode":"        exc_type: type[BaseException] | None,\n        exc_value: BaseException | None,\n        exc_traceback: TracebackType | None,\n    ) -> None:\n        \"\"\"Release the underlying video writer when leaving the context.\"\"\"\n        if self.__writer is not None:\n            self.__writer.release()\n            self.__writer = None\n\n\ndef _validate_and_setup_video(\n    source_path: str, start: int, end: int | None, iterative_seek: bool = False\n) -> tuple[cv2.VideoCapture, int, int]:\n    video = cv2.VideoCapture(source_path)\n    if not video.isOpened():\n        raise Exception(f\"Could not open video at {source_path}\")\n    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))\n    if end is not None and end > total_frames:\n        raise Exception(\"Requested frames are outbound\")\n    start = max(start, 0)\n    end = min(end, total_frames) if end is not None else total_frames\n\n    if iterative_seek:\n        while start > 0:\n            success = video.grab()\n            if not success:\n                break\n            start -= 1\n    elif start > 0:\n        video.set(cv2.CAP_PROP_POS_FRAMES, start)\n\n    return video, start, end\n\n\ndef get_video_frames_generator(\n    source_path: str,\n    stride: int = 1,","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/utils/video.py#L160-L196","documentation":"Raised by _validate_and_setup_video() in supervision.utils.video when the requested `end` frame index exceeds the video's total frame count (cv2.CAP_PROP_FRAME_COUNT). The guard prevents callers from silently iterating past the end of the file, which would otherwise yield nothing or corrupt seek behavior.","triggerScenarios":"Calling sv.get_video_frames_generator(source_path, start=0, end=10000) on a 538-frame video; hardcoding end for a batch of videos of different lengths; CAP_PROP_FRAME_COUNT returning a slightly smaller value than the container metadata claims.","commonSituations":"Processing a folder of videos with one fixed frame range; using frame counts copied from a different (longer) video; some codecs report frame counts that drift from the true value, so an end equal to a nominal count can still trip it.","solutions":["Query the real length first: info = sv.VideoInfo.from_video_path(path); use end=min(end, info.total_frames).","Omit `end` entirely — it defaults to the full video.","For variable-length batches, clamp per file rather than using a global constant."],"exampleFix":"// before\nfor f in sv.get_video_frames_generator(path, start=0, end=10000):  # 538-frame video\n\n// after\ninfo = sv.VideoInfo.from_video_path(path)\nfor f in sv.get_video_frames_generator(path, start=0, end=info.total_frames):","handlingStrategy":"validation","validationCode":"info = sv.VideoInfo.from_video_path(path)\nend = min(end, info.total_frames) if end is not None else None\nfor frame in sv.get_video_frames_generator(path, start=start, end=end):\n    ...","typeGuard":null,"tryCatchPattern":"try:\n    frames = sv.get_video_frames_generator(path, end=end)\nexcept Exception as e:\n    if 'outbound' in str(e):\n        info = sv.VideoInfo.from_video_path(path)\n        frames = sv.get_video_frames_generator(path, end=info.total_frames)\n    else:\n        raise","preventionTips":["Never hardcode end across heterogeneous videos; clamp it to total_frames per file.","Treat frame counts from metadata as approximate; leave a small margin."],"tags":["video","opencv","bounds-check"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}