{"record":{"id":"e99e499f5a808e8d","repo":"kovidgoyal/kitty","slug":"failed-to-render-len-unseen-out-of-len-m-fra","errorCode":null,"errorMessage":"Failed to render {len(unseen)} out of {len(m)} frames of animation","messagePattern":"Failed to render (.+?) out of (.+?) frames of animation","errorType":"exception","errorClass":"ConvertFailed","httpStatus":null,"severity":"error","filePath":"kittens/tui/images.py","lineNumber":283,"sourceCode":"                sz, pos = parts[3].split('+', 1)\n                f.canvas_width, f.canvas_height = map(positive_int, sz.split('x', 1))\n                f.canvas_x, f.canvas_y = map(int, pos.split('+', 1))\n            except Exception:\n                raise OutdatedImageMagick(f'Unexpected output filename: {x!r} produced by ImageMagick command: {last_imagemagick_cmd}')\n            f.path = output_prefix + f'-{index}.{m.mode}'\n            os.rename(os.path.join(tdir, x), f.path)\n            check_resize(f)\n    f = ans.frames[0]\n    if f.width != ans.width or f.height != ans.height:\n        with open(f.path, 'r+b') as ff:\n            data = ff.read()\n            ff.seek(0)\n            ff.truncate()\n            cd = create_canvas(data, f.width, f.canvas_x, f.canvas_y, ans.width, ans.height, 3 if ans.mode == 'rgb' else 4)\n            ff.write(cd)\n    if get_multiple_frames:\n        if unseen:\n            raise ConvertFailed(path, f'Failed to render {len(unseen)} out of {len(m)} frames of animation')\n    elif not ans.frames[0].path:\n        raise ConvertFailed(path, 'Failed to render image')\n\n    return ans\n\n\ndef render_as_single_image(\n    path: str,\n    m: ImageData,\n    available_width: int,\n    available_height: int,\n    scale_up: bool,\n    tdir: str | None = None,\n    remove_alpha: str = '',\n    flip: bool = False,\n    flop: bool = False,\n) -> tuple[str, int, int]:\n    import tempfile","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/tui/images.py#L265-L301","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"# before\nimg = render_image(path, width=80, get_multiple_frames=True)  # ConvertFailed\n# after\ntry:\n    img = render_image(path, width=80, get_multiple_frames=True)\nexcept ConvertFailed:\n    img = render_image(path, width=80)  # single frame fallback","handlingStrategy":"fallback","validationCode":"import subprocess\ndef count_frames(path: str) -> int:\n    out = subprocess.run(['magick', 'identify', path], capture_output=True, text=True).stdout\n    return max(1, len(out.strip().splitlines()))","typeGuard":null,"tryCatchPattern":"from kittens.tui.images import ConvertFailed\ntry:\n    img = render_image(path, width=80, get_multiple_frames=True)\nexcept ConvertFailed:\n    img = render_image(path, width=80)  # single-frame fallback","preventionTips":["Pre-test animated files with magick identify","Fall back to single-frame rendering for animations","Keep ImageMagick current to avoid dropped frames"],"tags":["imagemagick","animated-gif","image-conversion","frames"],"backgroundTag":"external-tool-output-corrupt","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}