invoke-ai/InvokeAI · error · TimeoutError
Timed out decoding frames from {video_path}
Error message
Timed out decoding frames from {video_path} What it means
Raised by the streamed frame iterator when no result arrives from the decoder worker within the inactivity `timeout` window. The deadline is reset on every frame, so this fires only when the worker stalls entirely mid-decode. It prevents callers of iter_video_frames from hanging forever on a wedged decoder.
Source
Thrown at invokeai/app/util/video_thumbnails.py:303
if record_size > MAX_DECODED_FRAME_RECORD_BYTES:
raise ValueError(f"Decoded frame record exceeds {MAX_DECODED_FRAME_RECORD_BYTES} bytes")
payload = read_exactly(record_size)
put_result(("frame", np.load(io.BytesIO(payload), allow_pickle=False)))
except (EOFError, ValueError, OSError) as error:
put_result(("done", error))
reader = threading.Thread(target=read_frames, name="video-frame-reader", daemon=True)
stderr_reader = threading.Thread(target=drain_stderr, name="video-stderr-reader", daemon=True)
reader.start()
stderr_reader.start()
deadline = time.monotonic() + (timeout if first_frame_timeout is None else first_frame_timeout)
try:
while True:
if is_canceled is not None and is_canceled():
raise CanceledException
remaining = deadline - time.monotonic()
if remaining <= 0:
raise TimeoutError(f"Timed out decoding frames from {video_path}")
try:
kind, value = results.get(timeout=min(0.1, remaining))
except queue.Empty:
continue
if kind == "frame":
if not isinstance(value, np.ndarray):
raise ValueError(f"Decoder returned an invalid frame for {video_path}")
yield value
deadline = time.monotonic() + timeout
continue
try:
return_code = proc.wait(timeout=min(1, timeout))
except subprocess.TimeoutExpired as error:
_terminate_process_tree(proc)
stderr_reader.join(timeout=1)
detail = read_stderr()
message = f"Timed out waiting for video decoder worker for {video_path}"
raise TimeoutError(f"{message}: {detail}" if detail else message) from errorView on GitHub (pinned to 0b6a024f2f)
Solutions
- Increase the timeout argument to iter_video_frames for high-resolution/long-GOP content.
- Validate/transcode the input with ffmpeg before decoding to rule out corruption.
- Check CPU availability for the worker subprocess (container CPU limits, cgroup throttling).
- Catch TimeoutError from iteration and skip/fail that video gracefully, terminating consumption of the generator.
Example fix
// before
for frame in iter_video_frames(path, timeout=30): ... # TimeoutError mid-stream
// after
try:
for frame in iter_video_frames(path, timeout=300):
process(frame)
except TimeoutError:
mark_video_failed(path, reason="decoder stall") Defensive patterns
Strategy: try-catch
Validate before calling
# pre-decode sanity check
if probe_video(path, timeout=30) is None:
raise UnsupportedMediaError(path) Try / catch
try:
for frame in iter_video_frames(path, timeout=300):
process(frame)
except TimeoutError as e:
if "Timed out decoding frames" in str(e):
fail_job(path, "decoder stalled") Prevention
- Use generous inactivity timeouts for high-res/long-GOP video
- Pre-verify files with probe_video or ffprobe
- Ensure adequate CPU for worker subprocesses
- Handle cancellation so stalled jobs can be aborted early
When it happens
Trigger: Calling iter_video_frames on a video where the decode worker hangs (corrupt file, deadlocked ffmpeg child), or where decoding the first frame alone takes longer than `timeout`; also if the consumer blocks the generator so long that inter-frame gaps exceed timeout? No — the deadline resets after each yielded frame, so it only triggers when the worker produces nothing within timeout.
Common situations: Videos with damaged moov atoms or corrupt packets stalling ffmpeg; extremely large first GOP on long-GOP 4K footage with a short timeout; CPU-starved containers making decode slower than timeout.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Video decode worker timed out after {timeout}s
- Input video {i} ({self.videos[i].video_name}) decoded to zer
- Video {self.video.video_name} has no decodable frames (probe
- Failed to extract frame {index} from {self.video.video_name}
- Video {self.video.video_name} has no decodable frames (probe
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/47f5d28c9f78d094.
Report an issue: GitHub.