ultralytics/ultralytics · error · ConnectionError
{st}Failed to read images from {s}
Error message
{st}Failed to read images from {s} What it means
Raised by LoadStreams when a capture opens successfully (isOpened() true) but the very first cap.read() returns success=False or a None frame. Some sources advertise themselves as open yet deliver no data — empty/corrupt video files, cameras that negotiate but never send frames, or streams where the first frame times out. The constructor guarantees a first frame before background reading starts, so failure here is fatal.
Source
Thrown at ultralytics/data/loaders.py:147
if s == 0 and (IS_COLAB or IS_KAGGLE):
raise NotImplementedError(
"'source=0' webcam not supported in Colab and Kaggle notebooks. "
"Try running 'source=0' in a local environment."
)
self.caps[i] = cv2.VideoCapture(s) # store video capture object
if not self.caps[i].isOpened():
raise ConnectionError(f"{st}Failed to open {s}")
w = int(self.caps[i].get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(self.caps[i].get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = self.caps[i].get(cv2.CAP_PROP_FPS) # warning: may return 0 or nan
self.frames[i] = max(int(self.caps[i].get(cv2.CAP_PROP_FRAME_COUNT)), 0) or float(
"inf"
) # infinite stream fallback
self.fps[i] = max((fps if math.isfinite(fps) else 0) % 100, 0) or 30 # 30 FPS fallback
success, im = self.caps[i].read() # guarantee first frame
if not success or im is None:
raise ConnectionError(f"{st}Failed to read images from {s}")
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)[..., None] if self.cv2_flag == cv2.IMREAD_GRAYSCALE else im
self.imgs[i].append(im)
self.shape[i] = im.shape
self.threads[i] = Thread(target=self.update, args=([i, self.caps[i], s]), daemon=True)
LOGGER.info(f"{st}Success ✅ ({self.frames[i]} frames of shape {w}x{h} at {self.fps[i]:.2f} FPS)")
self.threads[i].start()
except Exception:
self.close() # release opened captures and stop started threads before re-raising
raise
LOGGER.info("") # newline
def update(self, i: int, cap: cv2.VideoCapture, stream: str):
"""Read stream frames in daemon thread and update image buffer."""
n, f = 0, self.frames[i] # frame number, total frames
while self.running and cap.isOpened() and n < (f - 1):
if len(self.imgs[i]) < 30: # keep a <=30-image buffer
n += 1
cap.grab() # .read() = .grab() followed by .retrieve()View on GitHub (pinned to 0449ea011c)
Solutions
- Verify the file/stream independently: ffprobe file.mp4 (or ffplay for live sources) to confirm it actually contains decodable frames.
- For cameras, try the other substream URL (e.g. /stream2 vs /stream1) or lower resolution path that the camera serves reliably.
- Re-download or re-record corrupted video files; check file size is plausible.
- For flaky networks, add a small retry wrapper that reconstructs LoadStreams; transient first-frame timeouts often succeed on a second attempt.
Example fix
# before
cap = cv2.VideoCapture("corrupt.mp4") # opens, but read() -> (False, None)
# after
import subprocess
subprocess.run(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=nb_frames", "corrupt.mp4"], check=True)
# re-export if ffprobe also fails: ffmpeg -i broken.mp4 -c:v libx264 -c:a copy fixed.mp4 Defensive patterns
Strategy: retry
Validate before calling
import cv2
def stream_yields_frame(source: str) -> bool:
cap = cv2.VideoCapture(source)
try:
return cap.isOpened() and cap.read()[0]
finally:
cap.release() Try / catch
import time
for attempt in range(2):
try:
results = model.predict(source=src, stream=True)
break
except ConnectionError as e:
if attempt == 1 or "Failed to read" not in str(e):
raise
time.sleep(2) # first-frame timeouts on live sources are often transient Prevention
- Validate cap.read() returns a frame, not just isOpened(), for live sources.
- Use ffprobe/ffplay to confirm media actually flows from cameras.
- For files, confirm non-zero size and valid container before inference.
When it happens
Trigger: Passing a zero-byte or header-only video file; an RTSP source that completes handshake but the camera sends no media (e.g. wrong substream path); a stream whose codec opens but decoding the first packet fails. Raised after the same close-and-reraise cleanup as other LoadStreams errors, so partial resources are released.
Common situations: Corrupted downloads of .mp4 files; IP cameras whose main stream is disabled so the URL opens but yields nothing; multicast streams where the client joined but no traffic arrives; network hiccup at exactly the first read.
Related errors
- {st}Failed to open {s}
- Failed to open video {path}
- Image Not Found {f}
- Unable to read image source {!r}.
- Please use the corresponding methods in SAM2VideoPredictor f
AI-assisted analysis of ultralytics/ultralytics@0449ea011c (2026-08-15).
Data as JSON: /api/errors/72d7c531cbac2ab4.
Report an issue: GitHub.