{"record":{"id":"2d0bd6d1b6779f81","repo":"Comfy-Org/ComfyUI","slug":"the-prompt-references-image-idx-but-only-total","errorCode":null,"errorMessage":"The prompt references @Image{idx}, but only {total_images} reference images are connected (a batched input counts once per image).","messagePattern":"The prompt references @Image(.+?), but only (.+?) reference images are connected \\(a batched input counts once per image\\)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_api_nodes/nodes_grok.py","lineNumber":111,"sourceCode":"def _normalize_grok_reference_prompt(prompt: str, total_images: int, voices: list[str]) -> str:\n    \"\"\"Rewrite @Image1/@Audio1 style references (1-based, shared partner-node syntax)\n    into Grok's native <IMAGE_0>/<AUDIO_0> tags; an unnumbered @image/@audio means the first one.\n    Native tags pass through untouched. @ImageN refers to the Nth reference image overall, in\n    input order — a batched input contributes one number per image. @AudioN refers to the\n    'voice_N' widget; the API only accepts compact arrays, so voices are remapped to array\n    positions and 'none' slots between selected voices are harmless. Substitution repeats until\n    stable so adjacent tags like '@Image1@Image2' all resolve.\"\"\"\n    audio_indices: dict[int, int] = {}\n    for slot, voice in enumerate(voices, start=1):\n        if voice != \"none\":\n            audio_indices[slot] = len(audio_indices)\n\n    def repl(match: re.Match) -> str:\n        kind = match.group(1).lower()\n        idx = int(match.group(\"idx\") or 1)\n        if kind == \"image\":\n            if not 1 <= idx <= total_images:\n                raise ValueError(\n                    f\"The prompt references @Image{idx}, but only {total_images} \"\n                    f\"reference images are connected (a batched input counts once per image).\"\n                )\n            return f\"<IMAGE_{idx - 1}>\"\n        if idx not in audio_indices:\n            if 1 <= idx <= len(voices):\n                raise ValueError(f\"The prompt references @Audio{idx}, but 'voice_{idx}' is set to 'none'.\")\n            raise ValueError(f\"The prompt references @Audio{idx}, but only voices 1..{len(voices)} exist.\")\n        return f\"<AUDIO_{audio_indices[idx]}>\"\n\n    prev = None\n    while prev != prompt:\n        prev = prompt\n        prompt = _GROK_REF_TAG_RE.sub(repl, prompt)\n    return prompt\n\n\ndef _extract_grok_price(response) -> float | None:","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_api_nodes/nodes_grok.py#L93-L129","documentation":"In the Grok audio/video prompt preprocessing, @ImageN reference tags are rewritten to internal <IMAGE_{N-1}> markers. If the prompt references an image index greater than the number of connected reference images (total_images), rewriting fails with this error. Note the semantics: a batched input counts once per image in total_images, so the check is against the flattened count.","triggerScenarios":"A prompt containing '@Image5' (or '@Image' which defaults to idx 1 with total_images == 0) where the connected reference images number fewer than 5. _GROK_REF_TAG_RE matches @image/@Image with optional digits, case-insensitive; substitution loops until stable so adjacent tags all get resolved.","commonSituations":"Editing a prompt template written for more images than are currently wired; forgetting that unplugging one image socket shifts valid indices; batched tensor counted per image causing an off-by-N when a batch is replaced by a single image; typos like '@Image9' for '@Image0'.","solutions":["Fix the tag to reference an existing image: 1..total_images (1-based).","Connect the missing reference image(s) so the index becomes valid.","Remove stale @Image tags if the referenced image is intentionally gone."],"exampleFix":"# before (only 2 reference images connected)\nprompt = \"blend @Image1 and @Image3 styles\"  # raises\n\n# after\nprompt = \"blend @Image1 and @Image2 styles\"","handlingStrategy":"validation","validationCode":"import re\n_TAG = re.compile(r\"(?<!\\w)@image(?P<idx>\\d*)(?!\\w)\", re.IGNORECASE)\nrefs = {int(m.group(\"idx\") or 1) for m in _TAG.finditer(prompt)}\nbad = [i for i in refs if not 1 <= i <= total_images]\nassert not bad, f\"prompt references missing images {bad}; connected={total_images}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate all @ImageN tags against the connected image count before executing.","Regenerate prompt templates whenever image sockets are added/removed.","Remember indices are 1-based and a batch counts once per image."],"tags":["grok","xai","prompt-template","input-validation","reference-tag","comfy-api-nodes"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}