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 None

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Increase the timeout argument passed to extract_video_frame/probe_video_with_codec/decoder_frame_count for large or long videos.
  2. 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.
  3. Check system load / available CPU; decoding is CPU-bound, so reduce concurrency (the library already caps via _VIDEO_DECODER_SLOTS).
  4. 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

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

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/d27b4b401eb67136. Report an issue: GitHub.