huggingface/candle · error
shape mismatch on {path}: {shape:?} <> {tensor_shape:?}
Error message
shape mismatch on {path}: {shape:?} <> {tensor_shape:?} What it means
VarMap::get looks up a variable by path and validates that the requested shape matches the stored tensor's shape. If a variable already exists under that path but with a different shape than requested, the library bails instead of silently reusing or reshaping it. This protects callers from accidentally sharing a cached variable that has incompatible dimensions.
Source
Thrown at candle-nn/src/var_map.rs:108
}
Ok(())
}
/// Retrieve or add a new variable.
pub fn get<S: Into<Shape>>(
&self,
shape: S,
path: &str,
init: crate::Init,
dtype: DType,
device: &Device,
) -> Result<Tensor> {
let shape = shape.into();
let mut tensor_data = self.data.lock().unwrap();
if let Some(tensor) = tensor_data.get(path) {
let tensor_shape = tensor.shape();
if &shape != tensor_shape {
candle::bail!("shape mismatch on {path}: {shape:?} <> {tensor_shape:?}")
}
return Ok(tensor.as_tensor().clone());
}
let var = init.var(shape, dtype, device)?;
let tensor = var.as_tensor().clone();
tensor_data.insert(path.to_string(), var);
Ok(tensor)
}
pub fn data(&self) -> &Mutex<HashMap<String, Var>> {
&self.data
}
}
View on GitHub (pinned to d5fee525bf)
Solutions
- Make the requested shape match the shape the variable was originally created with (print tensor_shape from the error to compare).
- If shapes intentionally differ, use a different path/name for the new variable or clear the VarMap (create a fresh one) before rebuilding.
- When loading a safetensors/var-builder map, verify the model config used to compute shapes matches the checkpoint's config.
- If a reshape is what you want, fetch the existing tensor and reshape it explicitly rather than calling get with a mismatched shape.
Example fix
// before let w = var_map.get(( vocab, hidden ), DType::F32, "h.model.weight", init)?; // vocab changed to 32000 // after let w = var_map.get(( 32000, hidden ), DType::F32, "h.model.weight", init)?; // match stored shape
Defensive patterns
Strategy: validation
Validate before calling
let stored = var_map.data.lock().unwrap().get(path).map(|t| t.shape().clone());
if let Some(s) = &stored {
assert_eq!(s, &shape, "VarMap '{path}' shape {s:?} != requested {shape:?}");
} Type guard
fn shape_matches(stored: &candle::Shape, requested: &[usize]) -> bool {
stored.dims() == requested
} Try / catch
match var_map.get(shape, dtype, path, init) {
Ok(t) => t,
Err(e) if e.to_string().contains("shape mismatch") => {
// rebuild with fresh VarMap or corrected shape
let mut fresh = VarMap::new();
fresh.get(shape, dtype, path, init)?
}
Err(e) => return Err(e),
} Prevention
- Derive variable shapes from a single config struct so two build paths can't diverge
- Keep one VarMap per model instance; never reuse across differently-configured builds
- Log/checkpoint shapes on creation to compare against later get() calls
- Validate checkpoint tensor shapes against model config before load
When it happens
Trigger: Calling VarMap::get (directly or via var/get helpers) with a shape argument that differs from the shape the variable was first created with under the same path; typically across two model builds in one process where layer sizes changed (e.g. different vocab size, hidden size, or batch dims).
Common situations: Re-running a model-construction function twice in one process with a different config; loading pretrained weights whose shapes don't match the model definition; typos causing two different layers to collide on the same path.
Related errors
- backward not supported for non uniform upscaling factors
- in_channel mismatch between input ({c_in}) and kernel ({c_in
- slice-assign: the range for dim {i} ({start_included}..{end_
- unsupported 'value' data-type {dt:?} for {name}
- Wrong shape for input_ids or attention_mask
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/e366346fcbf9926f.
Report an issue: GitHub.