Comfy-Org/ComfyUI · error · ValueError

Aspect ratio `{ar:.2g}` must be {op} {hi:.2g}.

Error message

Aspect ratio `{ar:.2g}` must be {op} {hi:.2g}.

What it means

Raised by _assert_ratio_bounds() in comfy_api_nodes/util/validation_utils.py when a numeric aspect ratio is at or above the provider's maximum ratio (strict mode rejects equality too; strict=False allows ar == hi). Mirrors the min-bound check; bounds given as tuples like (4, 1) meaning 4:1, with automatic order normalization if the caller swapped min/max.

Source

Thrown at comfy_api_nodes/util/validation_utils.py:230

    min_ratio: tuple[float, float] | None = None,
    max_ratio: tuple[float, float] | None = None,
    strict: bool = True,
) -> None:
    """Validate a numeric aspect ratio against optional min/max ratio bounds."""
    lo = _ratio_from_tuple(min_ratio) if min_ratio is not None else None
    hi = _ratio_from_tuple(max_ratio) if max_ratio is not None else None

    if lo is not None and hi is not None and lo > hi:
        lo, hi = hi, lo  # normalize order if caller swapped them

    if lo is not None:
        if (ar <= lo) if strict else (ar < lo):
            op = "<" if strict else "≤"
            raise ValueError(f"Aspect ratio `{ar:.2g}` must be {op} {lo:.2g}.")
    if hi is not None:
        if (ar >= hi) if strict else (ar > hi):
            op = "<" if strict else "≤"
            raise ValueError(f"Aspect ratio `{ar:.2g}` must be {op} {hi:.2g}.")


def _parse_aspect_ratio_string(ar_str: str) -> float:
    """Parse 'X:Y' with integer parts into a positive float ratio X/Y."""
    parts = ar_str.split(":")
    if len(parts) != 2:
        raise ValueError(f"Aspect ratio must be 'X:Y' (e.g., 16:9), got '{ar_str}'.")
    try:
        a = int(parts[0].strip())
        b = int(parts[1].strip())
    except ValueError as exc:
        raise ValueError(f"Aspect ratio must contain integers separated by ':', got '{ar_str}'.") from exc
    if a <= 0 or b <= 0:
        raise ValueError(f"Aspect ratio parts must be positive integers, got {a}:{b}.")
    return a / b

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Reduce the aspect ratio to below the provider maximum (commonly 4:1).
  2. Verify width/height wiring — a swap turns 4:1 into 1:4 and trips the other bound.
  3. Use a preset ratio from the node's dropdown known to be supported.
  4. For genuinely extreme formats, generate at max ratio and crop/resize locally afterward.

Example fix

# before
_assert_ratio_bounds(5.0, max_ratio=(4, 1))  # ValueError: Aspect ratio `5` must be < 4.

# after
_assert_ratio_bounds(3.5, max_ratio=(4, 1))  # 7:2, inside bounds
Defensive patterns

Strategy: validation

Validate before calling

MAX = 4/1
if ar >= MAX:
    ar = MAX - 1e-6  # or clamp / reject with a friendly message

Try / catch

try: _assert_ratio_bounds(ar, max_ratio=(4,1)) except ValueError as e: raise UserVisibleError(str(e)) from e

Prevention

When it happens

Trigger: Calling a node wrapped with _assert_ratio_bounds(ar, max_ratio=(4,1)) with ar >= 4.0 — e.g. a 5:1 ultrawide banner request. Strict mode also rejects exactly 4.0; the message embeds '<' as the required relation.

Common situations: Ultrawide banner/cinematic requests beyond provider support; width/height swapped upstream inverting the ratio; custom-ratio widgets used with values outside the provider's supported list.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/2691faab5247101a. Report an issue: GitHub.