unslothai/unsloth · error · ValueError

The source image has no usable aspect ratio ({aspect_width}x

Error message

The source image has no usable aspect ratio ({aspect_width}x{aspect_height}).

What it means

h3_canvas_for_aspect raises ValueError when aspect_width or aspect_height is <= 0, i.e. the source image has a degenerate dimension so the aspect ratio is undefined (division would produce zero/infinity/NaN). This is the guard before the ratio math and the 1:4..4:1 range check, so a 0x0 or negative-dimension image fails here rather than producing nonsense canvas sizes.

Source

Thrown at studio/backend/core/inference/video_minimax_h3.py:259

H3_CANVAS_SHORT_EDGE = 768
H3_CANVAS_MAX_PIXELS = 768 * 1344
H3_CANVAS_MULTIPLE = 32
# Trained aspect-ratio range.
H3_MIN_ASPECT_RATIO = 1 / 4
H3_MAX_ASPECT_RATIO = 4

# Upstream stretches the first frame and center cover-crops the last.
H3_ANCHOR_FIRST = "first"
H3_ANCHOR_LAST = "last"


def h3_canvas_for_aspect(aspect_width: float, aspect_height: float) -> tuple[int, int]:
    """Resolve MiniMax-H3's canvas for an aspect ratio.

    Raises ValueError outside the trained 1:4 to 4:1 range.
    """
    if aspect_width <= 0 or aspect_height <= 0:
        raise ValueError(
            f"The source image has no usable aspect ratio ({aspect_width}x{aspect_height})."
        )
    ratio = aspect_width / aspect_height
    if not H3_MIN_ASPECT_RATIO <= ratio <= H3_MAX_ASPECT_RATIO:
        raise ValueError(
            f"MiniMax-H3 supports aspect ratios from 1:4 to 4:1; this image is "
            f"{aspect_width:g}x{aspect_height:g} ({ratio:.2f}:1). Crop it first."
        )
    if ratio >= 1.0:
        width, height = H3_CANVAS_SHORT_EDGE * ratio, float(H3_CANVAS_SHORT_EDGE)
    else:
        width, height = float(H3_CANVAS_SHORT_EDGE), H3_CANVAS_SHORT_EDGE / ratio
    area = width * height
    if area > H3_CANVAS_MAX_PIXELS:
        scale = math.sqrt(H3_CANVAS_MAX_PIXELS / area)
        width, height = width * scale, height * scale
    snap = lambda v: max(  # noqa: E731
        H3_CANVAS_MULTIPLE, round(v / H3_CANVAS_MULTIPLE) * H3_CANVAS_MULTIPLE

View on GitHub (pinned to 203007d190)

Solutions

  1. Validate the source image has width > 0 and height > 0 before calling (or before upload).
  2. Fix the upstream image load that produced a zero/negative dimension.
  3. Reject empty uploads at the request boundary with a clear 400.

Example fix

# before
canvas = h3_canvas_for_aspect(img.width, img.height)  # img is 0x0 -> ValueError

# after
if img.width <= 0 or img.height <= 0:
    raise HTTPException(400, "source image is empty")
canvas = h3_canvas_for_aspect(img.width, img.height)
Defensive patterns

Strategy: validation

Validate before calling

if img.width <= 0 or img.height <= 0:
    raise ValueError(f"source image is empty ({img.width}x{img.height})")
canvas = h3_canvas_for_aspect(img.width, img.height)

Type guard

def has_usable_size(img) -> bool:
    return img.width > 0 and img.height > 0

Try / catch

try:
    canvas = h3_canvas_for_aspect(w, h)
except ValueError as e:
    if "no usable aspect ratio" in str(e):
        raise HTTPException(400, "source image is empty or corrupt") from e
    raise

Prevention

When it happens

Trigger: Calling h3_canvas_for_aspect(0, 0), (0, 512), or with negative dims; passing a placeholder/uninitialized image whose size tuple is (0, 0); a fully transparent or failed decode upstream reporting zero size.

Common situations: Bugs where an image object was created but never loaded (PIL Image.new with 0 size, or a failed download handing back a stub); metadata-driven code computing size from arithmetic that can go to zero.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/882aecf54463e7e1. Report an issue: GitHub.