kovidgoyal/kitty · error · ConvertFailed
Failed to render {len(unseen)} out of {len(m)} frames of ani
Error message
Failed to render {len(unseen)} out of {len(m)} frames of animation What it means
Raised (as ConvertFailed) by render_image when multi-frame animation rendering was requested (get_multiple_frames=True) but some frames listed by ImageMagick were never produced: after processing, the 'unseen' set of expected frame filenames is non-empty. This means IM failed mid-animation or skipped frames.
Source
Thrown at kittens/tui/images.py:283
sz, pos = parts[3].split('+', 1)
f.canvas_width, f.canvas_height = map(positive_int, sz.split('x', 1))
f.canvas_x, f.canvas_y = map(int, pos.split('+', 1))
except Exception:
raise OutdatedImageMagick(f'Unexpected output filename: {x!r} produced by ImageMagick command: {last_imagemagick_cmd}')
f.path = output_prefix + f'-{index}.{m.mode}'
os.rename(os.path.join(tdir, x), f.path)
check_resize(f)
f = ans.frames[0]
if f.width != ans.width or f.height != ans.height:
with open(f.path, 'r+b') as ff:
data = ff.read()
ff.seek(0)
ff.truncate()
cd = create_canvas(data, f.width, f.canvas_x, f.canvas_y, ans.width, ans.height, 3 if ans.mode == 'rgb' else 4)
ff.write(cd)
if get_multiple_frames:
if unseen:
raise ConvertFailed(path, f'Failed to render {len(unseen)} out of {len(m)} frames of animation')
elif not ans.frames[0].path:
raise ConvertFailed(path, 'Failed to render image')
return ans
def render_as_single_image(
path: str,
m: ImageData,
available_width: int,
available_height: int,
scale_up: bool,
tdir: str | None = None,
remove_alpha: str = '',
flip: bool = False,
flop: bool = False,
) -> tuple[str, int, int]:
import tempfileView on GitHub (pinned to 6d5d0c4406)
Solutions
- Test the same file with 'magick identify file.gif' and a manual convert to see if IM drops frames
- Upgrade ImageMagick to a recent version
- Catch ConvertFailed for animations and fall back to rendering a single frame (get_multiple_frames=False)
Example fix
# before
img = render_image(path, width=80, get_multiple_frames=True) # ConvertFailed
# after
try:
img = render_image(path, width=80, get_multiple_frames=True)
except ConvertFailed:
img = render_image(path, width=80) # single frame fallback Defensive patterns
Strategy: fallback
Validate before calling
import subprocess
def count_frames(path: str) -> int:
out = subprocess.run(['magick', 'identify', path], capture_output=True, text=True).stdout
return max(1, len(out.strip().splitlines())) Try / catch
from kittens.tui.images import ConvertFailed
try:
img = render_image(path, width=80, get_multiple_frames=True)
except ConvertFailed:
img = render_image(path, width=80) # single-frame fallback Prevention
- Pre-test animated files with magick identify
- Fall back to single-frame rendering for animations
- Keep ImageMagick current to avoid dropped frames
When it happens
Trigger: Calling render_image(..., get_multiple_frames=True) on an animated GIF/WebP where ImageMagick reports N frames in its output listing but generates fewer files (e.g. frames where 'unseen' filenames remain after the rename loop).
Common situations: Animated GIFs with disposal/optimization that trip IM bugs; partial disk-full conditions in the temp dir; ImageMagick versions that silently drop duplicate frames; corrupted animations where IM aborts partway.
Related errors
- ImageMagick failed to convert {} correctly, it generated {}
- Unexpected output filename: {x!r} produced by ImageMagick co
- ImageMagick is required to process images
- Failed to find the ImageMagick convert executable, make sure
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/e99e499f5a808e8d.
Report an issue: GitHub.