{"record":{"id":"3d023a9cf8abc893","repo":"huggingface/candle","slug":"pixel-values-require-image-grid-thw","errorCode":null,"errorMessage":"pixel_values require image_grid_thw","messagePattern":"pixel_values require image_grid_thw","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-transformers/src/models/qwen3_vl/mod.rs","lineNumber":93,"sourceCode":"                self.text.dtype,\n                input_ids.device(),\n            )?)\n        } else {\n            None\n        };\n\n        let mut input_embeds = self.text.embed_tokens(input_ids)?;\n        let (batch_size, seq_len, hidden_dim) = input_embeds.dims3()?;\n        let device = input_embeds.device().clone();\n\n        let mut image_mask_opt: Option<Tensor> = None;\n        let mut video_mask_opt: Option<Tensor> = None;\n        let mut deepstack_image_opt: Option<Vec<Tensor>> = None;\n        let mut deepstack_video_opt: Option<Vec<Tensor>> = None;\n\n        if let Some(pixel_values) = &pixel_values {\n            let Some(image_grid_thw_ref) = image_grid_thw.as_ref() else {\n                candle::bail!(\"pixel_values require image_grid_thw\");\n            };\n            let mut pixel_values = pixel_values.clone();\n            let dims = pixel_values.dims();\n            if dims.len() == 3 {\n                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","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-transformers/src/models/qwen3_vl/mod.rs#L75-L111","documentation":"Thrown by qwen3_vl's forward when pixel_values (image tensors) are supplied but image_grid_thw is None. The vision encoder needs the (temporal, height, width) grid per image to reshape the flattened pixel values and compute positional information; providing pixel values without the grid is an inconsistent input.","triggerScenarios":"Calling Model::forward with Some(pixel_values) and image_grid_thw: None, e.g. when the caller preprocesses images but drops or forgets to pass the grid tensor returned by the processor.","commonSituations":"Hand-rolling the image preprocessing pipeline and forgetting the grid_thw output; using a processor version that returns the grid separately from pixel values; wiring up multimodal inputs for the first time.","solutions":["Pass the image_grid_thw tensor produced alongside pixel_values by the Qwen3-VL processor","Check that your preprocessing step actually returns both pixel_values and image_grid_thw and both are forwarded","If sending only text, pass pixel_values as None instead of a tensor with no grid"],"exampleFix":"// before\nmodel.forward(&input_ids, Some(&pixel_values), None, None, None)?;\n// after\nmodel.forward(&input_ids, Some(&pixel_values), Some(&image_grid_thw), None, None)?;","handlingStrategy":"validation","validationCode":"if pixel_values.is_some() && image_grid_thw.is_none() {\n    anyhow::bail!(\"pixel_values provided without image_grid_thw\");\n}","typeGuard":"fn valid_image_inputs(pixel_values: Option<&Tensor>, grid: Option<&Tensor>) -> bool {\n    match (pixel_values, grid) {\n        (Some(_), Some(_)) | (None, _) => true,\n        (Some(_), None) => false,\n    }\n}","tryCatchPattern":"match model.forward(&input_ids, pixel_values.as_ref(), image_grid_thw.as_ref(), None, None) {\n    Ok(l) => l,\n    Err(e) if e.to_string().contains(\"pixel_values require image_grid_thw\") => {\n        anyhow::bail!(\"preprocessing dropped image_grid_thw; fix the processor call\")\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always destructure processor output as a pair and pass both fields","Make pixel_values/grid a single struct so they can't be split","Pass None for both when running text-only inference"],"tags":["rust","candle","qwen3-vl","multimodal","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}