kovidgoyal/kitty · error · ConvertFailed

ImageMagick failed to convert {} correctly, it generated {}

Error message

ImageMagick failed to convert {} correctly, it generated {} < {} of data (w={}, h={}, bpp={})

What it means

Raised (as ConvertFailed) by check_resize when the output file produced by ImageMagick is smaller than width*height*bytes_per_pixel, and the missing bytes are not a whole number of rows — i.e. the file is truncated in a way that cannot be repaired by simply lowering the frame height. This works around known ImageMagick bugs that emit short files (see kitty issue #276).

Source

Thrown at kittens/tui/images.py:241

            resize_cmd = ['-coalesce'] + resize_cmd + ['-deconstruct']
        cmd += resize_cmd
    cmd += ['-depth', '8', '-set', 'filename:f', '%w-%h-%g-%p']
    ans = RenderedImage(m.fmt, width, height, m.mode)
    if only_first_frame:
        ans.frames = [Frame(m.frames[0])]
    else:
        ans.frames = list(map(Frame, m.frames))
    bytes_per_pixel = 3 if m.mode == 'rgb' else 4

    def check_resize(frame: Frame) -> None:
        # ImageMagick sometimes generates RGBA images smaller than the specified
        # size. See https://github.com/kovidgoyal/kitty/issues/276 for examples
        sz = os.path.getsize(frame.path)
        expected_size = bytes_per_pixel * frame.width * frame.height
        if sz < expected_size:
            missing = expected_size - sz
            if missing % (bytes_per_pixel * width) != 0:
                raise ConvertFailed(
                    path,
                    'ImageMagick failed to convert {} correctly, it generated {} < {} of data (w={}, h={}, bpp={})'.format(
                        path, sz, expected_size, frame.width, frame.height, bytes_per_pixel
                    ),
                )
            frame.height -= missing // (bytes_per_pixel * frame.width)
            if frame.index == 0:
                ans.height = frame.height
                ans.width = frame.width

    with tempfile.TemporaryDirectory(dir=os.path.dirname(output_prefix)) as tdir:
        output_template = os.path.join(tdir, f'im-%[filename:f].{m.mode}')
        if get_multiple_frames:
            cmd.append('+adjoin')
        run_imagemagick(path, cmd + [output_template])
        unseen = {x.index for x in m}
        for x in os.listdir(tdir):
            try:

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Upgrade (or downgrade) ImageMagick to a version known to work, preferably IM7 'magick'
  2. Verify/re-download the source image (file corruption) and try converting with 'magick convert' manually to reproduce
  3. Catch ConvertFailed and skip/fallback for that image

Example fix

# before
img = render_image(path, width=cols)  # ConvertFailed on buggy IM
# after
try:
    img = render_image(path, width=cols)
except ConvertFailed:
    img = None  # skip preview for this file
Defensive patterns

Strategy: try-catch

Validate before calling

import os
from PIL import Image  # optional pre-check of source integrity
def source_looks_ok(path: str) -> bool:
    try:
        with Image.open(path) as im:
            im.verify()
        return True
    except Exception:
        return False

Try / catch

from kittens.tui.images import ConvertFailed
try:
    img = render_image(path, width=cols)
except ConvertFailed as e:
    log.warning('skipping unconvertible image %s: %s', path, e)
    img = None

Prevention

When it happens

Trigger: Calling render_image() on an image that ImageMagick converts incorrectly (buggy IM version, or exotic/corrupt input); check_resize detects sz < expected_size with missing % (bpp*width) != 0, so the safe height-adjustment path cannot apply.

Common situations: Using an old or distro-patched ImageMagick with known short-output bugs; feeding partially downloaded or truncated images; CMYK/16-bit/exotic-format inputs that IM mishandles at certain output sizes.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/23964a65c911595a. Report an issue: GitHub.