invoke-ai/InvokeAI · error · VideoDecodeTimeoutError
Video decode worker timed out after {timeout}s
Error message
Video decode worker timed out after {timeout}s What it means
Raised (as VideoDecodeTimeoutError) when the spawned video-decode worker subprocess does not finish within `timeout` seconds during proc.communicate(). The worker process tree is terminated first, and this error is only raised when raise_on_timeout is True; otherwise the caller gets None. It exists so high-level APIs fail fast instead of hanging on pathological videos.
Source
Thrown at invokeai/app/util/video_thumbnails.py:189
With ``raise_on_timeout``, a timeout raises VideoDecodeTimeoutError instead of
returning None, letting callers distinguish "could not decode" from "ran out of
time on a loaded machine".
"""
monitor_stop: threading.Event | None = None
monitor: threading.Thread | None = None
try:
proc = _spawn_worker(*args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
except Exception:
return None
try:
monitor_stop, _memory_exceeded, monitor = _start_worker_memory_monitor(proc)
stdout, _ = proc.communicate(timeout=timeout)
except subprocess.TimeoutExpired as error:
_terminate_process_tree(proc)
proc.communicate()
if raise_on_timeout:
raise VideoDecodeTimeoutError(f"Video decode worker timed out after {timeout}s") from error
return None
except Exception:
# An unexpected failure (e.g. OSError from communicate()) must not leak the
# worker tree: the finally below stops the RSS-monitor backstop, so nothing
# else would ever reap a still-running worker and its ffmpeg child.
_terminate_process_tree(proc)
return None
finally:
if monitor_stop is not None and monitor is not None:
monitor_stop.set()
monitor.join(timeout=1)
if proc.returncode != 0:
return None
try:
result = json.loads(stdout)
except ValueError:
return None
return result if isinstance(result, dict) else NoneView on GitHub (pinned to 0b6a024f2f)
Solutions
- Increase the timeout argument passed to extract_video_frame/probe_video_with_codec/decoder_frame_count for large or long videos.
- Test the file manually: time ffmpeg -i video.mp4 -f null - to see if the file itself is pathologically slow to decode, and pre-transcode if so.
- Check system load / available CPU; decoding is CPU-bound, so reduce concurrency (the library already caps via _VIDEO_DECODER_SLOTS).
- Catch VideoDecodeTimeoutError and fall back to a lower-resolution proxy video for thumbnailing.
Example fix
// before
frame = extract_video_frame(path, timestamp=0) # VideoDecodeTimeoutError after 60s
// after
try:
frame = extract_video_field(path, timestamp=0, timeout=300)
except VideoDecodeTimeoutError:
frame = None # fall back to placeholder thumbnail Defensive patterns
Strategy: try-catch
Validate before calling
# rough pre-check: is the file pathologically big?
import os
if os.path.getsize(path) > 2_000_000_000:
timeout = 600 # allow more time for huge files Try / catch
from invokeai.app.util.video_thumbnails import VideoDecodeTimeoutError
try:
result = _run_worker(args, timeout, raise_on_timeout=True)
except VideoDecodeTimeoutError:
result = None # retry with larger timeout or mark job failed Prevention
- Scale timeout to video size/duration
- Pre-transcode long 4K footage to proxies
- Avoid scheduling many decodes on CPU-starved machines
- Monitor worker durations and tune timeout from p95 metrics
When it happens
Trigger: Calling _run_worker_unbounded (via _run_worker with raise_on_timeout=True) with a video large/long enough that decoding exceeds the timeout, a worker that deadlocks (e.g. stdout pipe backpressure), or an extremely small timeout value. Also when the machine is heavily loaded and the subprocess is starved of CPU.
Common situations: Thumbnail generation on a multi-hour 4K video with a 60s default timeout; CI machines with throttled CPU; worker memory limit causing swap thrashing; accidentally passing timeout=0.001 in tests or config.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- No frames decoded from {video_path}
- Timed out decoding frames from {video_path}
- {message}: {detail}
- Input video {i} ({self.videos[i].video_name}) decoded to zer
- 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/d27b4b401eb67136.
Report an issue: GitHub.