invoke-ai/InvokeAI · error · TimeoutError

{message}: {detail}

Error message

{message}: {detail}

What it means

Raised (as TimeoutError) when, after the worker sent its final message, proc.wait() did not observe exit within the remaining timeout — the decoder process failed to terminate in time. The process tree is killed first, and any captured stderr is appended to the message for diagnosis. Message text is 'Timed out waiting for video decoder worker for {path}: {stderr tail}'.

Source

Thrown at invokeai/app/util/video_thumbnails.py:321

                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 error
            if return_code != 0:
                stderr_reader.join(timeout=1)
                detail = read_stderr()
                message = f"Unable to decode video at {video_path}"
                raise ValueError(f"{message}: {detail}" if detail else message) from value
            return
    finally:
        memory_monitor_stop.set()
        memory_monitor.join(timeout=1)
        stopped.set()
        if proc.poll() is None:
            _terminate_process_tree(proc)
        proc.stdout.close()
        proc.wait()
        reader.join(timeout=1)
        stderr_reader.join(timeout=1)
        proc.stderr.close()

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Increase the timeout so the worker has time to exit cleanly after the last frame.
  2. Avoid decoding directly from flaky network URLs — copy to local disk first, then decode.
  3. Check for stuck ffmpeg subprocesses (ps aux | grep ffmpeg) and kill them; investigate why they refuse to exit.
  4. Read the stderr detail in the exception — it usually names the underlying decoder problem.

Example fix

// before
frames = list(iter_video_frames(url, timeout=15))  # TimeoutError waiting for worker
// after
local = download_to_temp(url)
try:
    frames = list(iter_video_frames(local, timeout=120))
finally:
    local.unlink()
Defensive patterns

Strategy: try-catch

Try / catch

try:
    for frame in iter_video_frames(path, timeout=120):
        ...
except TimeoutError as e:
    if "waiting for video decoder worker" in str(e):
        log.warning("decoder lingered: %s", e)  # stderr detail is in message
        cleanup_stray_ffmpeg()

Prevention

When it happens

Trigger: iter_video_frames reaching end-of-stream while the worker process lingers past the deadline — e.g. an ffmpeg child that ignores shutdown, a wedged worker after producing its last frame, or a timeout so small that even process teardown exceeds it.

Common situations: Very tight timeouts on slow/loaded machines; ffmpeg child processes stuck on a broken pipe or network source (e.g. decoding from an HTTP URL that stalls); zombie process accumulation preventing clean reaping.

Related errors


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