invoke-ai/InvokeAI · error · RuntimeError
Unable to open video decoder output stream
Error message
Unable to open video decoder output stream
What it means
Raised when the spawned ffmpeg/worker process used for streamed frame iteration was created but its stdout or stderr pipe is None, meaning the output streams could not be opened. This is essentially an OS-level pipe-creation/resource failure or an invalid Popen configuration. The worker process tree is terminated before raising to avoid leaking processes.
Source
Thrown at invokeai/app/util/video_thumbnails.py:244
is_canceled: Optional[Callable[[], bool]] = None,
first_frame_timeout: Optional[float] = None,
) -> Iterator[np.ndarray]:
"""Streams decoded frames from an isolated worker with bounded memory and wait time.
``timeout`` bounds decoder *inactivity*: it is restarted after every frame, so a long
video is not killed for being long. ``first_frame_timeout`` overrides that budget for
the first frame only, letting a caller that already spent part of the budget waiting
for capacity charge that wait against the same deadline instead of granting a fresh one.
"""
proc = _spawn_worker(
"stream",
str(video_path),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
if proc.stdout is None or proc.stderr is None:
_terminate_process_tree(proc)
raise RuntimeError("Unable to open video decoder output stream")
memory_monitor_stop, _memory_exceeded, memory_monitor = _start_worker_memory_monitor(proc)
results: queue.Queue[tuple[str, object]] = queue.Queue(maxsize=1)
stopped = threading.Event()
stderr_tail = bytearray()
def read_stderr() -> str:
return bytes(stderr_tail).decode(errors="replace").strip()
def drain_stderr() -> None:
while chunk := proc.stderr.read(4096):
stderr_tail.extend(chunk)
if len(stderr_tail) > MAX_DECODE_STDERR_BYTES:
del stderr_tail[:-MAX_DECODE_STDERR_BYTES]
def read_exactly(size: int) -> bytes:
chunks: list[bytes] = []
remaining = sizeView on GitHub (pinned to 0b6a024f2f)
Solutions
- Raise the file-descriptor limit (ulimit -n / container RLIMIT_NOFILE, e.g. 65536) and retry.
- Check for fd leaks in the application (lsof | wc -l) — leaked pipes from previous jobs will exhaust the limit.
- Reduce concurrency of iter_video_frames calls so fewer simultaneous pipes are open.
- If the error persists on a stock install, report it — with the library's own Popen config this should be unreachable.
Example fix
// before for frame in iter_video_frames(path): ... # RuntimeError: Unable to open video decoder output stream // after import resource resource.setrlimit(resource.RLIMIT_NOFILE, (65536, 65536)) # in service startup for frame in iter_video_frames(path): ...
Defensive patterns
Strategy: retry
Validate before calling
# check fd headroom before heavy video work
import os, resource
soft, _ = resource.getrlimit(resource.RLIMIT_NOFILE)
assert soft > 1024, f"fd limit too low: {soft}" Try / catch
try:
for frame in iter_video_frames(path):
...
except RuntimeError as e:
if "output stream" in str(e):
raise FdExhaustionError("raise RLIMIT_NOFILE and retry") from e Prevention
- Raise RLIMIT_NOFILE in containers (e.g. 65536)
- Audit for fd leaks (open pipes/sockets) app-wide
- Cap concurrent iter_video_frames users
- Re-run the job after load drops; this error is usually transient
When it happens
Trigger: subprocess.Popen returning a process whose stdout/stderr is None despite stdout=subprocess.PIPE — practically only when pipes fail to allocate (fd exhaustion, ulimit -n too low), or if the Popen call was modified to not use PIPE.
Common situations: Servers with very low file-descriptor limits running many concurrent video jobs; containers with small RLIMIT_NOFILE; a fd leak elsewhere in the app exhausting descriptors.
Related errors
- No frames decoded from {video_path}
- Video decode worker timed out after {timeout}s
- {message}: {detail}
- Video must use a browser-compatible H.264/AVC codec
- Video has no decodable frame
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/43a9dab46119281d.
Report an issue: GitHub.