roboflow/supervision · error · Exception

Requested frames are outbound

Error message

Requested frames are outbound

What it means

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.

Source

Thrown at src/supervision/utils/video.py:178

        exc_type: type[BaseException] | None,
        exc_value: BaseException | None,
        exc_traceback: TracebackType | None,
    ) -> None:
        """Release the underlying video writer when leaving the context."""
        if self.__writer is not None:
            self.__writer.release()
            self.__writer = None


def _validate_and_setup_video(
    source_path: str, start: int, end: int | None, iterative_seek: bool = False
) -> tuple[cv2.VideoCapture, int, int]:
    video = cv2.VideoCapture(source_path)
    if not video.isOpened():
        raise Exception(f"Could not open video at {source_path}")
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    if end is not None and end > total_frames:
        raise Exception("Requested frames are outbound")
    start = max(start, 0)
    end = min(end, total_frames) if end is not None else total_frames

    if iterative_seek:
        while start > 0:
            success = video.grab()
            if not success:
                break
            start -= 1
    elif start > 0:
        video.set(cv2.CAP_PROP_POS_FRAMES, start)

    return video, start, end


def get_video_frames_generator(
    source_path: str,
    stride: int = 1,

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Query the real length first: info = sv.VideoInfo.from_video_path(path); use end=min(end, info.total_frames).
  2. Omit `end` entirely — it defaults to the full video.
  3. For variable-length batches, clamp per file rather than using a global constant.

Example fix

// before
for f in sv.get_video_frames_generator(path, start=0, end=10000):  # 538-frame video

// after
info = sv.VideoInfo.from_video_path(path)
for f in sv.get_video_frames_generator(path, start=0, end=info.total_frames):
Defensive patterns

Strategy: validation

Validate before calling

info = sv.VideoInfo.from_video_path(path)
end = min(end, info.total_frames) if end is not None else None
for frame in sv.get_video_frames_generator(path, start=start, end=end):
    ...

Try / catch

try:
    frames = sv.get_video_frames_generator(path, end=end)
except Exception as e:
    if 'outbound' in str(e):
        info = sv.VideoInfo.from_video_path(path)
        frames = sv.get_video_frames_generator(path, end=info.total_frames)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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