{"record":{"id":"9c95fac219931550","repo":"Comfy-Org/ComfyUI","slug":"joyimage-reference-inputs-must-contain-one-image-e","errorCode":null,"errorMessage":"JoyImage reference inputs must contain one image each","messagePattern":"JoyImage reference inputs must contain one image each","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_extras/nodes_joyimage.py","lineNumber":46,"sourceCode":"    (1664, 576),\n    (1728, 576),\n    (1792, 512), (1792, 576),\n    (1856, 512),\n    (1920, 512),\n    (1984, 512),\n    (2048, 512),\n]\n# fmt: on\n\n\ndef _find_best_bucket(height: int, width: int) -> tuple[int, int]:\n    target_ratio = height / width\n    return min(BUCKETS_1024, key=lambda hw: abs(hw[0] / hw[1] - target_ratio))\n\n\ndef _resize_reference(image):\n    if image.shape[0] != 1:\n        raise ValueError(\"JoyImage reference inputs must contain one image each\")\n    samples = image.movedim(-1, 1)\n    bucket_h, bucket_w = _find_best_bucket(samples.shape[2], samples.shape[3])\n    resized = comfy.utils.common_upscale(samples, bucket_w, bucket_h, \"bilinear\", \"center\")\n    return resized.movedim(1, -1)[:, :, :, :3]\n\n\ndef _encode(clip, prompt, vae, images):\n    resized_images = [_resize_reference(image) for image in images]\n    conditioning = clip.encode_from_tokens_scheduled(clip.tokenize(prompt, images=resized_images))\n    if vae is not None and resized_images:\n        ref_latents = [vae.encode(image) for image in resized_images]\n        conditioning = node_helpers.conditioning_set_values(\n            conditioning, {\"reference_latents\": ref_latents}, append=True,\n        )\n    return conditioning\n\n\nclass TextEncodeJoyImageEdit(io.ComfyNode):","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_extras/nodes_joyimage.py#L28-L64","documentation":"Raised by _resize_reference() in the JoyImage (JoyCaption) reference pipeline: each reference image tensor passed to CLIP vision encoding must have batch dimension exactly 1, because the bucketing + resize path produces a single conditioning reference per image. Feeding a batched tensor (shape[0] > 1) raises immediately.","triggerScenarios":"Connecting a LoadImage batch or a video-frame batch (B>1) into the reference image input of the JoyImage encode node; upstream nodes that expand a single image into an animation batch.","commonSituations":"Batch workflows where every image input inherits a batch dimension; using image list nodes that concatenate frames into one tensor.","solutions":["Slice the batch before the node: pass image[0:1] so shape[0] == 1.","Use a batch-split node (e.g. ImageFromBatch / RepeatImageBatch with count 1) upstream.","For multiple references, wire each single image into the node's separate reference inputs rather than one batched tensor."],"exampleFix":"# before\nrefs = [image]           # image.shape == (8, H, W, 3) -> raises\n\n# after\nrefs = [image[i:i+1] for i in range(image.shape[0])]  # or just image[:1]","handlingStrategy":"validation","validationCode":"for name, image in zip(ref_names, images):\n    assert image.shape[0] == 1, f\"{name} has batch {image.shape[0]}; split it: image[i:i+1]\"","typeGuard":"def is_single_reference(image) -> bool:\n    return image.ndim == 4 and image.shape[0] == 1","tryCatchPattern":"try:\n    cond = _encode(clip, prompt, vae, images)\nexcept ValueError as e:\n    if \"one image each\" in str(e):\n        images = [im[0:1] for im in images]\n        cond = _encode(clip, prompt, vae, images)\n    else:\n        raise","preventionTips":["Slice batches to length 1 before JoyImage reference inputs.","Use batch-split nodes instead of feeding frame batches.","Wire multiple single images into separate reference inputs."],"tags":["batch","image","joycaption","validation","shape"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}