{"record":{"id":"4ec8f8c6275bd365","repo":"calesthio/OpenMontage","slug":"image-omni-prompt-placeholders-must-start-at-im","errorCode":null,"errorMessage":"Image Omni prompt placeholders must start at <<<image_1>>>","messagePattern":"Image Omni prompt placeholders must start at <<<image_1>>>","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/_kling/omni.py","lineNumber":36,"sourceCode":"        {\n            \"index\": index,\n            \"placeholder\": f\"<<<image_{index}>>>\",\n            \"source\": item.get(\"source\") or item.get(\"image\") or item.get(\"image_url\"),\n            \"source_type\": item.get(\"source_type\", \"unknown\"),\n        }\n        for index, item in enumerate(image_list, start=1)\n    ]\n    if not references:\n        return prompt, []\n\n    existing_numbers = [int(value) for value in PLACEHOLDER_RE.findall(prompt)]\n    if existing_numbers:\n        if max(existing_numbers) > len(references):\n            raise ValueError(\n                f\"prompt references <<<image_{max(existing_numbers)}>>> but only {len(references)} image(s) were provided\"\n            )\n        if min(existing_numbers) < 1:\n            raise ValueError(\"Image Omni prompt placeholders must start at <<<image_1>>>\")\n        return prompt, references\n\n    placeholders = \" \".join(item[\"placeholder\"] for item in references)\n    return f\"{prompt}\\nReferences: {placeholders}\", references\n","sourceCodeStart":18,"sourceCodeEnd":41,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/_kling/omni.py#L18-L41","documentation":"Raised when the prompt contains <<<image_N>>> placeholders and the smallest N is less than 1 — i.e. a <<<image_0>>> (or lower) placeholder is present. Kling Image Omni placeholders are 1-based, so image_0 is never valid.","triggerScenarios":"A prompt generated with 0-based indexing (common from code or LLMs that enumerate from 0), e.g. 'replace <<<image_0>>> with the product' with any number of references.","commonSituations":"Prompts written by looping code using enumerate() without start=1; LLM-authored prompts mixing 0-based and 1-based placeholders; template copy-paste from 0-based examples.","solutions":["Renumber placeholders to start at <<<image_1>>> (1-based)","If generating prompts programmatically, use enumerate(images, start=1)","Remove the invalid placeholder entirely if it was accidental"],"exampleFix":"// before\nprompt = f'blend <<<image_0>>> and <<<image_1>>>'  # 0-based, invalid\n\n// after\nprompt = 'blend <<<image_1>>> and <<<image_2>>>'  # 1-based\n# or programmatically:\nparts = [f'<<<image_{i}>>>' for i in range(1, len(images) + 1)]","handlingStrategy":"validation","validationCode":"import re\n\ndef placeholders_are_one_based(prompt: str) -> bool:\n    nums = [int(n) for n in re.findall(r'<<<image_(\\-?\\d+)>>>', prompt)]\n    return not nums or min(nums) >= 1","typeGuard":null,"tryCatchPattern":"try:\n    prompt, refs = build_image_references(prompt, images)\nexcept ValueError as e:\n    if 'must start at <<<image_1>>>' in str(e):\n        prompt = prompt.replace('<<<image_0>>>', '<<<image_1>>>')  # fix 0-based prompt\n        prompt, refs = build_image_references(prompt, images)\n    else:\n        raise","preventionTips":["Always use enumerate(images, start=1) when building placeholder prompts","Never hand-write <<<image_0>>> — the format is 1-based","Linter-check generated prompts for image_0 before submission"],"tags":["kling","omni","prompt","validation","off-by-one"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}