{"record":{"id":"76b3886685ea563a","repo":"Comfy-Org/ComfyUI","slug":"aspect-ratio-must-contain-integers-separated-by","errorCode":null,"errorMessage":"Aspect ratio must contain integers separated by ':', got '{ar_str}'.","messagePattern":"Aspect ratio must contain integers separated by ':', got '(.+?)'\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_api_nodes/util/validation_utils.py","lineNumber":242,"sourceCode":"        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":224,"sourceCodeEnd":246,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_api_nodes/util/validation_utils.py#L224-L246","documentation":"Raised by _parse_aspect_ratio_string() in comfy_api_nodes/util/validation_utils.py when the 'X:Y' string has the right shape but either part is not an integer (after whitespace stripping). int() raises ValueError internally and this message re-raises with provider-friendly context, chaining the original via 'from exc'.","triggerScenarios":"Passing '16.5:9', '1.78:1', ':9', '16:', or 'a:b' to validate_aspect_ratio. Floats, empty parts, and non-numeric text all land here. Only 'int:int' (whitespace around parts tolerated) parses.","commonSituations":"Users entering decimal ratios ('2.35:1' is actually valid because 2.35 is not an int — this fails); colon left with a missing side after editing; localized keyboards substituting characters; programmatic callers formatting floats directly into the string.","solutions":["Use whole-number components: '47:20' instead of '2.35:1', '16:9' instead of '1.78:1'.","When converting from a decimal, compute an integer approximation (e.g. Fraction(1.78).limit_denominator(50) -> '89:50').","Fill in both sides of the colon; ':9' and '16:' are invalid.","Prefer preset combo values when available."],"exampleFix":"# before\n_parse_aspect_ratio_string('2.35:1')  # ValueError: must contain integers separated by ':'\n\n# after\nfrom fractions import Fraction\nf = Fraction(2.35).limit_denominator(20)  # 47/20\nratio_str = f'{f.numerator}:{f.denominator}'  # '47:20'","handlingStrategy":"type-guard","validationCode":"from fractions import Fraction\n\ndef normalize_ratio(s: str) -> str:\n    parts = s.split(':')\n    if len(parts) != 2:\n        f = Fraction(float(s)).limit_denominator(50)\n        return f'{f.numerator}:{f.denominator}'\n    return s","typeGuard":"def is_int_ratio_string(s: str) -> bool:\n    parts = s.split(':')\n    if len(parts) != 2: return False\n    try:\n        int(parts[0].strip()); int(parts[1].strip()); return True\n    except ValueError:\n        return False","tryCatchPattern":null,"preventionTips":["Use integer components only — '2.35:1' fails, '47:20' works.","Both sides of the colon must be present.","Convert floats with Fraction.limit_denominator before formatting."],"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"}