{"record":{"id":"29b6188266a02561","repo":"sgl-project/sglang","slug":"video-placeholder-count-does-not-match-video-data","errorCode":null,"errorMessage":"Video placeholder count does not match video_data: {len(video_data)} video(s) given","messagePattern":"Video placeholder count does not match video_data: (.+?) video\\(s\\) given","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/dots_note_omni.py","lineNumber":454,"sourceCode":"                        audio_cap=audio_cap,\n                        audio_sr=audio_sr,\n                        k_mode=k_mode,\n                        max_new_tokens=max_new_tokens,\n                    ),\n                )\n                total_content_items += len(content)\n                total_frames += sum(item.get(\"type\") == \"image_url\" for item in content)\n                total_audio_segments += sum(\n                    item.get(\"type\") == \"audio_url\" for item in content\n                )\n                input_text, media = self._render_video_content(\n                    input_text, question, video_index, content\n                )\n                video_media.update(media)\n\n            leftover = self.video_placeholder_regex.search(input_text)\n            if leftover is not None:\n                raise ValueError(\n                    \"Video placeholder count does not match video_data: \"\n                    f\"{len(video_data)} video(s) given\"\n                )\n            input_text, image_data, audio_data = self._merge_video_media(\n                input_text, image_data, audio_data, video_media\n            )\n            preprocess_elapsed = time.perf_counter() - preprocess_started\n            logger.info(\n                \"[dots_mm] rid=%s video_preprocess elapsed=%.3fs \"\n                \"expanded_frames=%d expanded_audio_segments=%d content_items=%d \"\n                \"after_preprocess images=%d audios=%d\",\n                request_obj.rid,\n                preprocess_elapsed,\n                total_frames,\n                total_audio_segments,\n                total_content_items,\n                len(image_data),\n                len(audio_data),","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/dots_note_omni.py#L436-L472","documentation":"Raised by process_mm_data_async when, after substituting all supplied videos into their placeholders, a video placeholder token still remains in input_text. The count of video markers must equal len(video_data).","triggerScenarios":"The prompt/template contains more video placeholder tokens (matched by self.video_placeholder_regex) than entries in video_data — e.g. template renders 2 video tags but only 1 video was sent.","commonSituations":"Multi-video prompts built by hand or by a template that always emits N video slots; or a video item was dropped (None/failed download) before reaching the processor.","solutions":["Make the number of video placeholders in the prompt equal len(video_data)","If a video is optional, remove its placeholder when absent","Validate client-side: count video tokens in the prompt against your video list before sending"],"exampleFix":"// before\nprompt = \"<video> <video>\"  # 2 placeholders\nvideo_data = [v1]           # 1 video\n// after\nprompt = \"<video>\"          # 1 placeholder\nvideo_data = [v1]","handlingStrategy":"validation","validationCode":"import re\nVIDEO_RE = re.compile(r'<your-model-video-placeholder>')  # match server's video_placeholder_regex\ncount = len(VIDEO_RE.findall(prompt))\nassert count == len(video_data or []), f'{count} placeholders vs {len(video_data or [])} videos'","typeGuard":null,"tryCatchPattern":"try:\n    await processor.process_mm_data_async(...)\nexcept ValueError as e:\n    if 'Video placeholder count' in str(e):\n        rebuild prompt so placeholder count equals len(video_data); resubmit","preventionTips":["Build prompts with exactly one video token per video","Drop the placeholder when an optional video is absent"],"tags":["multimodal","video","placeholder-mismatch","valueerror"],"backgroundTag":"placeholder-count-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}