{"record":{"id":"bdcca89edd688b5b","repo":"Comfy-Org/ComfyUI","slug":"aspect-ratio-must-be-x-y-e-g-16-9-got-ar","errorCode":null,"errorMessage":"Aspect ratio must be 'X:Y' (e.g., 16:9), got '{ar_str}'.","messagePattern":"Aspect ratio must be 'X:Y' \\(e\\.g\\., 16:9\\), got '(.+?)'\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_api_nodes/util/validation_utils.py","lineNumber":237,"sourceCode":"\n    if lo is not None and hi is not None and lo > hi:\n        lo, hi = hi, lo  # normalize order if caller swapped them\n\n    if lo is not None:\n        if (ar <= lo) if strict else (ar < lo):\n            op = \"<\" if strict else \"≤\"\n            raise ValueError(f\"Aspect ratio `{ar:.2g}` must be {op} {lo:.2g}.\")\n    if hi is not None:\n        if (ar >= hi) if strict else (ar > hi):\n            op = \"<\" if strict else \"≤\"\n            raise ValueError(f\"Aspect ratio `{ar:.2g}` must be {op} {hi:.2g}.\")\n\n\ndef _parse_aspect_ratio_string(ar_str: str) -> float:\n    \"\"\"Parse 'X:Y' with integer parts into a positive float ratio X/Y.\"\"\"\n    parts = ar_str.split(\":\")\n    if len(parts) != 2:\n        raise ValueError(f\"Aspect ratio must be 'X:Y' (e.g., 16:9), got '{ar_str}'.\")\n    try:\n        a = int(parts[0].strip())\n        b = int(parts[1].strip())\n    except ValueError as exc:\n        raise ValueError(f\"Aspect ratio must contain integers separated by ':', got '{ar_str}'.\") from exc\n    if a <= 0 or b <= 0:\n        raise ValueError(f\"Aspect ratio parts must be positive integers, got {a}:{b}.\")\n    return a / b\n","sourceCodeStart":219,"sourceCodeEnd":246,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_api_nodes/util/validation_utils.py#L219-L246","documentation":"Raised by _parse_aspect_ratio_string() in comfy_api_nodes/util/validation_utils.py when a string aspect ratio does not contain exactly one ':' separator. The helper is used by the public validate_aspect_ratio() to accept widget values like '16:9'; it splits on ':' and requires exactly two parts before attempting integer parsing.","triggerScenarios":"Passing '16x9', '1.77', '16-9', '169', or '16:9:2' as an aspect-ratio string to a node that validates via validate_aspect_ratio('16x9'). Only the exact 'X:Y' two-part form is accepted.","commonSituations":"Custom-ratio widgets where users type the decimal form (1.78) common in other tools; pasted ratios with en-dashes or 'x' separators; API callers constructing the field programmatically with a float instead of the string form.","solutions":["Format the ratio as 'X:Y' with integer parts, e.g. '16:9' or '4:3'.","Convert decimals to the nearest integer ratio before passing (1.78 -> '16:9').","Prefer the node's preset ratio dropdown over free-text entry.","If calling from code, emit f'{w}:{h}' from integer width/height."],"exampleFix":"# before\n_parse_aspect_ratio_string('16x9')  # ValueError: Aspect ratio must be 'X:Y' (e.g., 16:9), got '16x9'.\n\n# after\n_parse_aspect_ratio_string('16:9')  # -> 1.777...","handlingStrategy":"validation","validationCode":"def is_ratio_string(s) -> bool:\n    return isinstance(s, str) and len(s.split(':')) == 2\n\nif not is_ratio_string(ratio_str):\n    raise ValueError(f\"ratio must be 'X:Y', got {ratio_str!r}\")","typeGuard":"def is_ratio_string(s) -> bool:\n    return isinstance(s, str) and len(s.split(':')) == 2","tryCatchPattern":null,"preventionTips":["Always type ratios as 'X:Y' with a single colon.","Convert decimals to integer pairs before entering them.","Use preset combo options when unsure of the format."],"tags":["api-nodes","validation","aspect-ratio","parsing"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}