roboflow/supervision · error · RuntimeError
write_frame requires an open VideoSink context.
Error message
write_frame requires an open VideoSink context.
What it means
Raised by VideoSink.write_frame() in supervision.utils.video when it is called while the internal cv2.VideoWriter is None — i.e. outside the `with sv.VideoSink(...)` context. The writer is created in __enter__ and released (set to None) in __exit__; writing outside that window would silently drop frames, so the invariant is enforced with a RuntimeError.
Source
Thrown at src/supervision/utils/video.py:155
)
# OpenCV can construct a writer object that is not usable for the target path.
if not self.__writer.isOpened():
self.__writer.release()
self.__writer = None
raise RuntimeError(f"Could not open video writer for {self.target_path}")
return self
def write_frame(self, frame: npt.NDArray[np.uint8]) -> None:
"""
Writes a single video frame to the target video file.
Args:
frame: The video frame to be written to the file. The frame
must be in BGR color format.
"""
# Preserve the context-manager invariant instead of silently dropping frames.
if self.__writer is None:
raise RuntimeError("write_frame requires an open VideoSink context.")
self.__writer.write(frame)
def __exit__(
self,
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)View on GitHub (pinned to 7f254d9784)
Solutions
- Move all write_frame calls inside the with-block: with sv.VideoSink(...) as sink: sink.write_frame(f).
- Do not cache the sink beyond the context; create a new one for each output file.
- If an exception hit inside the block, handle it there — after __exit__ the sink is closed by design.
Example fix
// before
sink = sv.VideoSink('out.mp4', info)
sink.write_frame(frame) # not opened
// after
with sv.VideoSink('out.mp4', info) as sink:
sink.write_frame(frame) Defensive patterns
Strategy: validation
Validate before calling
# write only inside the context; nothing to pre-check beyond structure
with sv.VideoSink(target_path, info) as sink:
for frame in frames:
sink.write_frame(frame) # always inside the with-block Try / catch
try:
sink.write_frame(frame)
except RuntimeError as e:
if 'open VideoSink context' in str(e):
raise RuntimeError('write_frame called outside with sv.VideoSink(...)') from e
raise Prevention
- Keep sink usage lexically inside the `with` block; never leak the sink reference out.
- In callbacks, pass the sink as a parameter scoped to the context, not a global.
When it happens
Trigger: Calling sink.write_frame(frame) before entering the context manager (e.g. after constructing VideoSink but before `with`); storing the sink and writing after the with-block exited; exception inside the with-body prematurely triggering __exit__ then code continuing to write.
Common situations: Refactoring loops out of the with-block but keeping the sink reference; a callback registered with sv.process_video outliving the sink; error paths that swallow the original exception and keep processing frames.
Related errors
- Cannot append to CSV: The file '{self.file_name}' is not ope
- Invalid value type: {type(value)}. Must be an instance of {c
- resolution must be a tuple of two integers, got
- Both dimensions in resolution must be positive. Got ({w}, {h
- Only class instances are supported, not classes.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/174e0a98591b900a.
Report an issue: GitHub.