roboflow/supervision · error · RuntimeError
Reader thread raised: {item}
Error message
Reader thread raised: {item} What it means
Raised by the frame queue consumer inside _prefetched_frames_generator (src/supervision/utils/video.py) when the background reader thread put an exception object into the queue instead of a frame. The consumer wraps it in RuntimeError, chaining the original exception, so the message names the underlying failure that occurred while opening or reading the video on the worker thread.
Source
Thrown at src/supervision/utils/video.py:368
while not stop_event.is_set():
try:
frame_queue.put(sentinel, timeout=0.1)
return
except Full:
pass
thread = threading.Thread(target=reader, daemon=True)
thread.start()
try:
while True:
try:
item = frame_queue.get(timeout=0.5)
except Empty:
if not thread.is_alive():
break
continue
if isinstance(item, BaseException):
raise RuntimeError(f"Reader thread raised: {item!r}") from item
if item is None:
break
yield item
finally:
stop_event.set()
thread.join(timeout=2.0)
def process_video(
source_path: str,
target_path: str,
callback: Callable[[npt.NDArray[np.uint8], int], npt.NDArray[np.uint8]],
*,
max_frames: int | None = None,
prefetch: int = 32,
writer_buffer: int = 32,
show_progress: bool = False,
progress_message: str = "Processing video",View on GitHub (pinned to 7f254d9784)
Solutions
- Read the tail of the message and the chained __cause__ to find the real failure, then fix that (usually file/codec related).
- Verify the source video opens synchronously first: sv.get_video_frames_generator(path) with prefetch=0 to get the raw error.
- Guard per-file processing in a try/except so one bad video does not kill a batch job.
- If the file is truncated, repair or re-encode it with ffmpeg before processing.
Example fix
// before
for frame in sv.get_video_frames_generator(path, prefetch=8):
... # RuntimeError: Reader thread raised: ...
// after
try:
for frame in sv.get_video_frames_generator(path, prefetch=8):
...
except RuntimeError as e:
log.warning('skipping %s: %s', path, e.__cause__ or e) Defensive patterns
Strategy: try-catch
Validate before calling
probe = cv2.VideoCapture(path)
readable = probe.isOpened()
probe.release()
if not readable:
raise RuntimeError(f'video not readable: {path}') Try / catch
try:
for frame in sv.get_video_frames_generator(path, prefetch=prefetch):
process(frame)
except RuntimeError as e:
if 'Reader thread raised' in str(e) and e.__cause__ is not None:
log.warning('reader failure on %s: %r', path, e.__cause__)
continue # skip to next file in a batch
raise Prevention
- Treat 'Reader thread raised' as a wrapper; always inspect __cause__ for the real error.
- Wrap per-video processing in try/except in batch pipelines.
- Verify file integrity (ffprobe) before enabling prefetch on untrusted inputs.
When it happens
Trigger: Calling sv.get_video_frames_generator(path, prefetch=N) where the reader thread hits an error — e.g. the video cannot be opened, a grab()/retrieve() fails mid-stream, or the file is truncated. The exception travels through the queue and is re-raised on the main thread during iteration.
Common situations: A video becomes unreadable or is deleted after the generator is created; truncated recordings from killed processes; network streams dropping mid-read; the error text 'Reader thread raised: ...' is a wrapper — the real cause follows after the colon and via __cause__.
Related errors
- Could not open video at {source_path}
- Requested frames are outbound
- Could not open video at {video_path}
- Could not open video writer for {self.target_path}
- All sigma values must be positive
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/7de955bdeb6bc586.
Report an issue: GitHub.