{"record":{"id":"72670474f5ea39b8","repo":"huggingface/candle","slug":"dtype-mismatch","errorCode":null,"errorMessage":"dtype mismatch","messagePattern":"dtype mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-core/src/cpu_backend/mod.rs","lineNumber":1758,"sourceCode":"    } else {\n        (v.exp() - T::one()) * alpha\n    }\n}\n\nimpl CpuStorage {\n    pub fn as_slice<D: WithDType>(&self) -> Result<&[D]> {\n        D::cpu_storage_as_slice(self)\n    }\n\n    pub fn concat(storages: &[CpuStorage]) -> Result<CpuStorage> {\n        let storage0 = &storages[0];\n        let s = match storage0 {\n            Self::U8(_) => {\n                let storages = storages\n                    .iter()\n                    .map(|s| match s {\n                        Self::U8(s) => Ok(s.as_slice()),\n                        _ => crate::bail!(\"dtype mismatch\"),\n                    })\n                    .collect::<Result<Vec<_>>>()?\n                    .concat();\n                Self::U8(storages)\n            }\n            Self::U32(_) => {\n                let storages = storages\n                    .iter()\n                    .map(|s| match s {\n                        Self::U32(s) => Ok(s.as_slice()),\n                        _ => crate::bail!(\"dtype mismatch\"),\n                    })\n                    .collect::<Result<Vec<_>>>()?\n                    .concat();\n                Self::U32(storages)\n            }\n            Self::I16(_) => {\n                let storages = storages","sourceCodeStart":1740,"sourceCodeEnd":1776,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-core/src/cpu_backend/mod.rs#L1740-L1776","documentation":"When concatenating CPU storages (cat op), candle groups input storages by dtype. All inputs must have the same storage variant as the first tensor (here U8); any tensor whose storage is not the expected variant triggers this bail. It guards against mixing dtypes in cat/concat.","triggerScenarios":"Tensor::cat(&tensors, dim) (or cat-related paths used by book_hub_1/book_hub_2) where the first tensor is u8 but at least one other tensor has a different dtype (f32, u32, i16, ...).","commonSituations":"Concatenating an image tensor (u8) with a normalized/converted tensor (f32); mixing indices (u32) with data tensors; a pipeline step that forgot a to_dtype conversion.","solutions":["Cast all tensors to a common dtype before cat: tensors.iter().map(|t| t.to_dtype(DType::F32)).collect().","Check the dtype of every input with t.dtype() and fix the source of the divergent tensor.","Move conversions (to_dtype) into the producing code instead of at the concat site.","If dtype divergence is intentional, use a different op (e.g. stack in a common dtype or keep separate tensors)."],"exampleFix":"// before\nlet cat = Tensor::cat(&[&u8_tensor, &f32_tensor], 0)?;\n// after\nlet cat = Tensor::cat(&[&u8_tensor.to_dtype(DType::F32)?, &f32_tensor], 0)?;","handlingStrategy":"validation","validationCode":"let dt = tensors[0].dtype();\nfor t in &tensors { if t.dtype() != dt { return Err(anyhow::anyhow!(\"cat: mixed dtypes {:?} vs {:?}\", dt, t.dtype())); } }","typeGuard":null,"tryCatchPattern":"match result { Err(e) if e.to_string().contains(\"dtype mismatch\") => { // unify dtypes and retry\n}, other => other?, }","preventionTips":["Normalize every tensor to a single pipeline dtype (usually f32) before concat.","Assert homogeneous dtypes in helper functions that accept tensor lists.","Trace where u8 image tensors and f32 tensors meet; insert to_dtype at boundaries."],"tags":["dtype","cat","tensor","rust"],"backgroundTag":"dtype-mismatch","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}