Comfy-Org/ComfyUI · error · ValueError

Exactly one image is required; got a batch. Pick one frame f

Error message

Exactly one image is required; got a batch. Pick one frame first.

What it means

Raised by the sync.so Talking Image node when the image input is a batch with more than one image. The endpoint animates a single portrait, so get_number_of_images(image) must equal 1. Unlike the video lipsync node, this node can auto-downscale oversized images, but batching has no equivalent escape.

Source

Thrown at comfy_api_nodes/nodes_sync_so.py:315

                IO.Hidden.unique_id,
            ],
            is_api_node=True,
            price_badge=IO.PriceBadge(
                expr="""{"type":"usd","usd":0.19019,"format":{"approximate":true,"suffix":"/second"}}""",
            ),
        )

    @classmethod
    async def execute(
        cls,
        image: Input.Image,
        audio: Input.Audio,
        prompt: str,
        seed: int,
        model: dict,
    ) -> IO.NodeOutput:
        if get_number_of_images(image) != 1:
            raise ValueError("Exactly one image is required; got a batch. Pick one frame first.")
        validate_audio_duration(audio, max_duration=600)

        height, width = get_image_dimensions(image)
        speaker_x, speaker_y = model["speaker_x"], model["speaker_y"]
        if max(width, height) > 4096 or width * height > 4096 * 2160:
            if not model["auto_downscale"]:
                raise ValueError(
                    f"sync.so rejects images above 4K (4096x2160); got {width}x{height}. "
                    "Downscale the image first or enable auto_downscale."
                )
            image = downscale_image_tensor(image, total_pixels=4096 * 2160)
            image = downscale_image_tensor_by_max_side(image, max_side=4096)
            new_height, new_width = get_image_dimensions(image)
            # speaker coordinates are given in the original image's pixel space
            speaker_x = min(new_width - 1, round(speaker_x * new_width / width))
            speaker_y = min(new_height - 1, round(speaker_y * new_height / height))

        if model["speaker_selection"] == "coordinates":

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Select exactly one frame from the batch upstream (slice or image-pick node)
  2. If animating several portraits, run the node once per image

Example fix

# before
talking_image(image=batch_tensor, audio=a)  # 4 images

# after
talking_image(image=batch_tensor[0:1], audio=a)  # single portrait
Defensive patterns

Strategy: validation

Validate before calling

assert get_number_of_images(image) == 1, "Talking Image needs exactly one portrait; slice the batch first"

Type guard

def is_single_portrait(image) -> bool:
    return get_number_of_images(image) == 1

Try / catch

try:
    await syncso_talking_image(image, audio, ...)
except ValueError as e:
    if "got a batch" in str(e):
        await syncso_talking_image(image[0:1], audio, ...)
    else:
        raise

Prevention

When it happens

Trigger: Connecting a multi-image tensor (shape[0] > 1) to the talking-image node's image input, e.g. frames from a video or a multi-view image set.

Common situations: Feeding an image-generation node's batched output directly; assuming the node picks the first frame automatically; decoding a short clip as an image batch.

Related errors


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