{"record":{"id":"72d7c531cbac2ab4","repo":"ultralytics/ultralytics","slug":"st-failed-to-read-images-from-s","errorCode":null,"errorMessage":"{st}Failed to read images from {s}","messagePattern":"(.+?)Failed to read images from (.+?)","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"ultralytics/data/loaders.py","lineNumber":147,"sourceCode":"                if s == 0 and (IS_COLAB or IS_KAGGLE):\n                    raise NotImplementedError(\n                        \"'source=0' webcam not supported in Colab and Kaggle notebooks. \"\n                        \"Try running 'source=0' in a local environment.\"\n                    )\n                self.caps[i] = cv2.VideoCapture(s)  # store video capture object\n                if not self.caps[i].isOpened():\n                    raise ConnectionError(f\"{st}Failed to open {s}\")\n                w = int(self.caps[i].get(cv2.CAP_PROP_FRAME_WIDTH))\n                h = int(self.caps[i].get(cv2.CAP_PROP_FRAME_HEIGHT))\n                fps = self.caps[i].get(cv2.CAP_PROP_FPS)  # warning: may return 0 or nan\n                self.frames[i] = max(int(self.caps[i].get(cv2.CAP_PROP_FRAME_COUNT)), 0) or float(\n                    \"inf\"\n                )  # infinite stream fallback\n                self.fps[i] = max((fps if math.isfinite(fps) else 0) % 100, 0) or 30  # 30 FPS fallback\n\n                success, im = self.caps[i].read()  # guarantee first frame\n                if not success or im is None:\n                    raise ConnectionError(f\"{st}Failed to read images from {s}\")\n                im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)[..., None] if self.cv2_flag == cv2.IMREAD_GRAYSCALE else im\n                self.imgs[i].append(im)\n                self.shape[i] = im.shape\n                self.threads[i] = Thread(target=self.update, args=([i, self.caps[i], s]), daemon=True)\n                LOGGER.info(f\"{st}Success ✅ ({self.frames[i]} frames of shape {w}x{h} at {self.fps[i]:.2f} FPS)\")\n                self.threads[i].start()\n        except Exception:\n            self.close()  # release opened captures and stop started threads before re-raising\n            raise\n        LOGGER.info(\"\")  # newline\n\n    def update(self, i: int, cap: cv2.VideoCapture, stream: str):\n        \"\"\"Read stream frames in daemon thread and update image buffer.\"\"\"\n        n, f = 0, self.frames[i]  # frame number, total frames\n        while self.running and cap.isOpened() and n < (f - 1):\n            if len(self.imgs[i]) < 30:  # keep a <=30-image buffer\n                n += 1\n                cap.grab()  # .read() = .grab() followed by .retrieve()","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/ultralytics/ultralytics/blob/0449ea011cfd6c9a0d50a0bf1043aca5190cd476/ultralytics/data/loaders.py#L129-L165","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ncap = cv2.VideoCapture(\"corrupt.mp4\")  # opens, but read() -> (False, None)\n\n# after\nimport subprocess\nsubprocess.run([\"ffprobe\", \"-v\", \"error\", \"-select_streams\", \"v:0\", \"-show_entries\", \"stream=nb_frames\", \"corrupt.mp4\"], check=True)\n# re-export if ffprobe also fails: ffmpeg -i broken.mp4 -c:v libx264 -c:a copy fixed.mp4","handlingStrategy":"retry","validationCode":"import cv2\n\ndef stream_yields_frame(source: str) -> bool:\n    cap = cv2.VideoCapture(source)\n    try:\n        return cap.isOpened() and cap.read()[0]\n    finally:\n        cap.release()","typeGuard":null,"tryCatchPattern":"import time\nfor attempt in range(2):\n    try:\n        results = model.predict(source=src, stream=True)\n        break\n    except ConnectionError as e:\n        if attempt == 1 or \"Failed to read\" not in str(e):\n            raise\n        time.sleep(2)  # first-frame timeouts on live sources are often transient","preventionTips":["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."],"tags":["streaming","video","opencv","corrupt-file"],"backgroundTag":null,"analyzedSha":"0449ea011cfd6c9a0d50a0bf1043aca5190cd476","analyzedAt":"2026-08-15T02:34:13.413Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}