Comfy-Org/ComfyUI · error · ValueError

Give one time per keyframe image: got {len(parts)} time(s) f

Error message

Give one time per keyframe image: got {len(parts)} time(s) for {image_count} image(s).

What it means

FLUX 3 keyframe timing requires exactly one comma-separated time value per keyframe image. The parser splits the times string on commas, drops empty parts, and raises when the count of parsed parts differs from the number of collected keyframe images.

Source

Thrown at comfy_api_nodes/nodes_bfl.py:1060

    for tensor in (images or {}).values():
        if tensor is None:
            continue
        if tensor.ndim == 4:
            flat.extend(tensor[i] for i in range(tensor.shape[0]))
        else:
            flat.append(tensor)
    if len(flat) > _FLUX3_MAX_IMAGES:
        raise ValueError(f"FLUX 3 supports at most {_FLUX3_MAX_IMAGES} {field_name}, got {len(flat)}.")
    for tensor in flat:
        _flux3_validate_image(tensor)
    return flat


def _flux3_parse_times(value: str, image_count: int, duration: int | str) -> list[float]:
    """Parse one keyframe time in seconds per image: increasing, inside the clip."""
    parts = [part.strip() for part in value.split(",") if part.strip()]
    if len(parts) != image_count:
        raise ValueError(
            f"Give one time per keyframe image: got {len(parts)} time(s) for {image_count} image(s)."
        )
    try:
        times = [float(part) for part in parts]
    except ValueError as exc:
        raise ValueError(f"Keyframe times must be numbers in seconds, comma-separated; got '{value}'.") from exc
    if not all(math.isfinite(time) for time in times):
        raise ValueError(f"Keyframe times must be finite numbers in seconds; got '{value}'.")
    if any(later <= earlier for earlier, later in zip(times, times[1:])):
        raise ValueError(f"Keyframe times must increase; got {times}.")
    if times[0] < 0:
        raise ValueError(f"Keyframe times cannot be negative; got {times[0]}.")
    cap = _FLUX3_MAX_DURATION if duration == "auto" else int(duration)
    if times[-1] > cap:
        raise ValueError(f"Keyframe time {times[-1]}s is past the end of a {cap}s clip.")
    return times

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Provide exactly image_count comma-separated values, e.g. '0, 4, 8.5' for 3 images.
  2. Re-count images after any change to the keyframe inputs and regenerate the string.
  3. Avoid trailing commas and empty segments.

Example fix

# before
keyframe_times = "0, 4"      # 3 images -> ValueError

# after
keyframe_times = "0, 4, 8.5"  # one per image
Defensive patterns

Strategy: validation

Validate before calling

parts = [p.strip() for p in value.split(",") if p.strip()]
assert len(parts) == image_count, f"{len(parts)} times for {image_count} images"

Type guard

def times_count_matches(value: str, image_count: int) -> bool:
    return len([p for p in value.split(",") if p.strip()]) == image_count

Prevention

When it happens

Trigger: Passing '0, 5' with 3 keyframe images, or trailing-comma strings like '0,5,' (empty parts are dropped, so counts shift), or forgetting to update times after adding an image.

Common situations: Adding/removing keyframe images without editing the times widget; copy-pasting times strings between nodes with different image counts.

Related errors


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