invoke-ai/InvokeAI · error · ValueError
Input video {i} ({self.videos[i].video_name}) decoded to zer
Error message
Input video {i} ({self.videos[i].video_name}) decoded to zero frames. What it means
Thrown in _iter_joined_frames when a decoder yields 0 frames for input video i during concat. The joiner needs at least one frame to build boundaries; a zero-frame clip makes concatenation impossible. Usually indicates a corrupt, empty, or wrongly-probed source file.
Source
Thrown at invokeai/app/invocations/video_concat.py:279
frame = np.ascontiguousarray(frame)
n_frames += 1
# The clip's first head_want frames are consumed into the boundary blend
# with the previous clip's tail rather than emitted directly.
if not head_complete:
b_head.append(frame)
if len(b_head) == head_want and blend is not None:
yield from blend(a_tail, b_head)
a_tail = []
b_head = []
head_complete = True
continue
# Hold back the last tail_keep frames seen so far; anything older is
# guaranteed not to be part of the next boundary and can be emitted.
tail_buf.append(frame)
if len(tail_buf) > tail_keep:
yield tail_buf.popleft()
if n_frames == 0:
raise ValueError(f"Input video {i} ({self.videos[i].video_name}) decoded to zero frames.")
if n_frames < head_want + tail_keep:
raise ValueError(
f"Clip {i} has {n_frames} frames but the requested transitions need "
f"{head_want} from its head + {tail_keep} from its tail. Lower "
f"transition_frames or use longer clips."
)
a_tail = list(tail_buf)
View on GitHub (pinned to 0b6a024f2f)
Solutions
- Check the clip plays in a normal player and is not empty
- Re-encode the clip to a standard codec (H.264) before concat
- Remove/replace the zero-frame clip in the videos list
- Verify the file path resolved by context.videos.get_path points to a real non-empty file
Example fix
// before videos=[VideoField(video_name='corrupt.mp4')] # decodes to 0 frames // after ffmpeg -i corrupt.mp4 -c:v libx264 fixed.mp4 videos=[VideoField(video_name='fixed.mp4')]
Defensive patterns
Strategy: validation
Validate before calling
import subprocess
n = subprocess.run(['ffprobe','-v','error','-select_streams','v:0','-count_frames','-show_entries','stream=nb_read_frames','-of','csv=p=0', path], capture_output=True, text=True)
if not n.stdout.strip() or n.stdout.strip() == '0':
raise ValueError(f'{path} decodes to zero frames') Type guard
def has_frames(probe_result) -> bool:
return bool(probe_result and probe_result.get('nb_read_frames', 0) > 0) Try / catch
try:
out = concat.invoke(context)
except ValueError as e:
if 'decoded to zero frames' in str(e):
videos = [v for v in videos if not is_empty_clip(v)]
out = rebuild(videos).invoke(context)
else:
raise Prevention
- Pre-flight check every input with ffprobe before concat
- Validate downloads complete (file size / hash)
- Re-encode unusual codecs to H.264 up front
When it happens
Trigger: invoke() -> _iter_joined_frames iterates video i; after the decode loop n_frames == 0 (decoder returned no frames).
Common situations: Empty or truncated video files in the input list; codec the decoder cannot handle; broken download producing a header-only file.
Related errors
- 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
- No frames decoded from {video_path}
- Video decode worker timed out after {timeout}s
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/02d03321efcfb84c.
Report an issue: GitHub.