{"record":{"id":"e3c4dc9d8ec9f331","repo":"Comfy-Org/ComfyUI","slug":"keyframe-times-must-increase-got-times","errorCode":null,"errorMessage":"Keyframe times must increase; got {times}.","messagePattern":"Keyframe times must increase; got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_api_nodes/nodes_bfl.py","lineNumber":1070,"sourceCode":"        _flux3_validate_image(tensor)\n    return flat\n\n\ndef _flux3_parse_times(value: str, image_count: int, duration: int | str) -> list[float]:\n    \"\"\"Parse one keyframe time in seconds per image: increasing, inside the clip.\"\"\"\n    parts = [part.strip() for part in value.split(\",\") if part.strip()]\n    if len(parts) != image_count:\n        raise ValueError(\n            f\"Give one time per keyframe image: got {len(parts)} time(s) for {image_count} image(s).\"\n        )\n    try:\n        times = [float(part) for part in parts]\n    except ValueError as exc:\n        raise ValueError(f\"Keyframe times must be numbers in seconds, comma-separated; got '{value}'.\") from exc\n    if not all(math.isfinite(time) for time in times):\n        raise ValueError(f\"Keyframe times must be finite numbers in seconds; got '{value}'.\")\n    if any(later <= earlier for earlier, later in zip(times, times[1:])):\n        raise ValueError(f\"Keyframe times must increase; got {times}.\")\n    if times[0] < 0:\n        raise ValueError(f\"Keyframe times cannot be negative; got {times[0]}.\")\n    cap = _FLUX3_MAX_DURATION if duration == \"auto\" else int(duration)\n    if times[-1] > cap:\n        raise ValueError(f\"Keyframe time {times[-1]}s is past the end of a {cap}s clip.\")\n    return times\n\n\nclass Flux3VideoNodeBase(IO.ComfyNode):\n    \"\"\"Shared widgets, request plumbing and polling for the FLUX 3 generation modes.\"\"\"\n\n    RATE_HD: float\n    RATE_FHD: float\n\n    @classmethod\n    def common_inputs(cls) -> list:\n        return [\n            IO.Combo.Input(","sourceCodeStart":1052,"sourceCodeEnd":1088,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_api_nodes/nodes_bfl.py#L1052-L1088","documentation":"Keyframe times define the order images appear in the FLUX 3 clip and must be strictly increasing. zip(times, times[1:]) checks every adjacent pair; equal or decreasing times desynchronize image-to-time mapping and are rejected.","triggerScenarios":"Passing duplicate times ('2, 2, 5'), unsorted times ('5, 2, 8'), or times generated without sorting.","commonSituations":"Copying a repeated default value for every image; building times from a dict or set whose iteration order is not sorted.","solutions":["Sort and deduplicate: times = sorted(set(times)).","Space them intentionally, e.g. evenly: [i * cap / (n - 1) for i in range(n)].","Double-check hand-edited strings for duplicated values."],"exampleFix":"# before\nkeyframe_times = \"5, 2, 8\"  # ValueError: not increasing\n\n# after\ntimes = sorted({5, 2, 8})  # [2, 5, 8]\nkeyframe_times = \", \".join(str(t) for t in times)","handlingStrategy":"validation","validationCode":"times = sorted(set(float(p) for p in value.split(\",\")))\nassert all(b > a for a, b in zip(times, times[1:])), \"times must strictly increase\"","typeGuard":"def times_strictly_increasing(times: list[float]) -> bool:\n    return all(b > a for a, b in zip(times, times[1:]))","tryCatchPattern":null,"preventionTips":["Build times with sorted(set(...)).","Never reuse one default value for every image.","Emit times from ordered data structures only."],"tags":["bfl","flux3","keyframes","ordering","input-validation"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}