{"record":{"id":"accc8076ad45f558","repo":"huggingface/candle","slug":"image-embedding-length-does-not-match-placehold","errorCode":null,"errorMessage":"Image embedding length {} does not match placeholder tokens {}","messagePattern":"Image embedding length (.+?) does not match placeholder tokens (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-transformers/src/models/qwen3_vl/mod.rs","lineNumber":116,"sourceCode":"                pixel_values = pixel_values.reshape((dims[0] * dims[1], dims[2]))?;\n            }\n            let (image_embeds, deepstack_image_embeds) =\n                self.vision.forward(&pixel_values, image_grid_thw_ref)?;\n            let image_embeds = image_embeds.to_device(&device)?.to_dtype(self.text.dtype)?;\n            let mut deepstack_image_embeds = deepstack_image_embeds\n                .into_iter()\n                .map(|t| t.to_device(&device)?.to_dtype(self.text.dtype))\n                .collect::<Result<Vec<_>>>()?;\n\n            let mut offset = 0usize;\n            let mut image_mask =\n                Tensor::zeros((batch_size, seq_len), DType::F32, input_ids.device())?;\n            let total_expected: usize = continuous_img_pad\n                .iter()\n                .flat_map(|spans| spans.iter().map(|(s, e)| e - s))\n                .sum();\n            if image_embeds.dim(0)? != total_expected {\n                candle::bail!(\n                    \"Image embedding length {} does not match placeholder tokens {}\",\n                    image_embeds.dim(0)?,\n                    total_expected\n                );\n            }\n\n            for (batch, spans) in continuous_img_pad.iter().enumerate() {\n                for &(start, end) in spans {\n                    let len = end - start;\n                    let chunk = image_embeds.narrow(0, offset, len)?;\n                    offset += len;\n                    input_embeds = input_embeds.slice_assign(\n                        &[batch..batch + 1, start..end, 0..hidden_dim],\n                        &chunk.unsqueeze(0)?,\n                    )?;\n                    let ones = Tensor::ones((1, len), DType::F32, input_ids.device())?;\n                    image_mask = image_mask.slice_assign(&[batch..batch + 1, start..end], &ones)?;\n                }","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-transformers/src/models/qwen3_vl/mod.rs#L98-L134","documentation":"Thrown by qwen3_vl's forward when the number of image embedding rows produced by the vision tower does not equal the number of image placeholder token positions (continuous_img_pad span lengths) found in input_ids. Each placeholder token must be replaced by exactly one image embedding; a mismatch would corrupt the merged sequence.","triggerScenarios":"Calling forward where vision_encoder(image pixel values) yields a different row count than sum of (end-start) over the continuous image placeholder spans — e.g. wrong grid_thw, wrong resize/crop settings, or stale placeholder spans in input_ids.","commonSituations":"Mismatched preprocessing (image resized differently than the grid implies); tokenization that emits a different number of image placeholders than patches; mixing pixel_values from one image with input_ids from another; batch size mismatch between modalities.","solutions":["Regenerate pixel_values and image_grid_thw with the same processor call that produced input_ids so patch count and placeholder count match","Verify grid_thw values divide evenly into patch tokens matching the number of <|image_pad|> tokens in input_ids","Ensure pixel_values and input_ids belong to the same example/batch"],"exampleFix":"// before (stale placeholders from an old processor run)\nlet input_ids = old_tokenizer_output; // 200 image pads\nlet (pixel_values, grid_thw) = new_processor(image)?; // 400 patches\nmodel.forward(&input_ids, Some(&pixel_values), Some(&grid_thw), None, None)?;\n// after\nlet inputs = processor(image, text)?; // consistent pair\nmodel.forward(&inputs.input_ids, Some(&inputs.pixel_values), Some(&inputs.image_grid_thw), None, None)?;","handlingStrategy":"validation","validationCode":"let total_pads: usize = image_span_spans.iter().flat_map(|s| s.iter().map(|(a,b)| b-a)).sum();\nif image_embeds.dim(0)? != total_pads {\n    anyhow::bail!(\"re-run the processor so patch count matches image placeholders\");\n}","typeGuard":null,"tryCatchPattern":"match model.forward(&input_ids, Some(&pixel_values), Some(&grid_thw), None, None) {\n    Ok(l) => l,\n    Err(e) if e.to_string().contains(\"does not match placeholder tokens\") => {\n        anyhow::bail!(\"pixel_values and input_ids are out of sync; regenerate both with one processor call\")\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Produce input_ids, pixel_values and grid_thw in a single processor invocation","Never reuse tokenized input_ids after changing image preprocessing","Count <|image_pad|> tokens and compare to grid_thw-derived patch count before forward"],"tags":["rust","candle","qwen3-vl","shape-mismatch","multimodal"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}