unslothai/unsloth · error · ValueError

The aspect ratio must be positive, got {aspect_width}:{aspec

Error message

The aspect ratio must be positive, got {aspect_width}:{aspect_height}.

What it means

Raised by the H3 canvas helper when aspect_width or aspect_height is zero or negative. The function mirrors MiniMax-H3's resolve_canvas_size arithmetic to size a training canvas before any diffusers import, and a non-positive edge makes the ratio (and every downstream dimension) undefined. It is a pure input-validation guard on the aspect pair.

Source

Thrown at studio/backend/core/training/diffusion_h3_clips.py:155

    return num_text_tokens + audio_rows + latent_frames * rows_per_frame


def h3_train_canvas(
    aspect_width: float,
    aspect_height: float,
    short_edge: int = H3_CANVAS_SHORT_EDGE,
    max_pixels: Optional[int] = None,
) -> tuple[int, int]:
    """MiniMax-H3's canvas rule, as ``(width, height)``.

    Identical arithmetic to the pipeline's ``resolve_canvas_size`` (which returns
    ``(height, width)``), re-expressed here so the trainer can size a dataset before any
    diffusers import. ``short_edge`` is the run's ``resolution``; the area cap scales with it
    so a smaller training canvas keeps the released aspect budget rather than the released
    pixel count.
    """
    if aspect_width <= 0 or aspect_height <= 0:
        raise ValueError(f"The aspect ratio must be positive, got {aspect_width}:{aspect_height}.")
    ratio = aspect_width / aspect_height
    if not H3_MIN_ASPECT_RATIO <= ratio <= H3_MAX_ASPECT_RATIO:
        raise ValueError(
            f"MiniMax-H3 was trained on aspect ratios from 1:4 to 4:1; this clip is "
            f"{aspect_width:g}x{aspect_height:g} ({ratio:.2f}:1). Crop it first."
        )
    if max_pixels is None:
        # The released cap, rescaled to the requested short edge: (1344/768) * short_edge^2.
        max_pixels = int(H3_CANVAS_MAX_PIXELS * (short_edge / H3_CANVAS_SHORT_EDGE) ** 2)
    if ratio >= 1.0:
        width, height = short_edge * ratio, float(short_edge)
    else:
        width, height = float(short_edge), short_edge / ratio
    area = width * height
    if area > max_pixels:
        scale = math.sqrt(max_pixels / area)
        width, height = width * scale, height * scale

View on GitHub (pinned to 203007d190)

Solutions

  1. Fix the producer of the aspect pair so both values are positive integers.
  2. Skip/log clips whose probed dimensions are non-positive instead of feeding them to the canvas helper.
  3. Validate dimensions when loading metadata.jsonl rows at ingestion time.

Example fix

# before
w, h = h3_canvas_size(0, 1080, short_edge=768)  # probe returned width 0

# after
if clip_width > 0 and clip_height > 0:
    w, h = h3_canvas_size(clip_width, clip_height, short_edge=768)
Defensive patterns

Strategy: validation

Validate before calling

def aspect_inputs_valid(w: int, h: int) -> bool:
    return isinstance(w, int) and isinstance(h, int) and w > 0 and h > 0

Prevention

When it happens

Trigger: Passing aspect_width=0 or a negative dimension; deriving the aspect from a clip probe that failed and returned zeros; integer underflow in aspect math (width - crop_left going below zero).

Common situations: Metadata/JSON rows carrying 0x0 dimensions; portrait/landscape branch swapping width and height into the wrong slots; degenerate clips whose decoder reported no size.

Related errors


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