huggingface/candle · error
Metal strided to_dtype
Error message
Metal strided to_dtype {left:?} {right:?} not implemented What it means
The strided (non-contiguous) Metal to_dtype path has its own kernel table; a cast between dtype pairs missing from that table triggers this bail. Strided layouts arise from slicing, transposing, or other view ops, so the same cast may work contiguous but fail strided.
Solutions
- Make the tensor contiguous first: tensor.contiguous()?.to_dtype(dtype)?
- Cast before the op that creates the strided layout
- Cast on CPU and move back to Metal
- Use a dtype pair present in the strided cast table
Example fix
// before let t = tensor.transpose(0, 1)?.to_dtype(DType::F16)?; // after let t = tensor.transpose(0, 1)?.contiguous()?.to_dtype(DType::F16)?;
Defensive patterns
Strategy: fallback
Validate before calling
if !tensor.is_contiguous() {
tensor = tensor.contiguous()?; // use contiguous cast path
}
tensor = tensor.to_dtype(target)?; Try / catch
match strided_tensor.to_dtype(target) {
Ok(t) => t,
Err(e) if e.to_string().contains("strided to_dtype") => {
strided_tensor.contiguous()?.to_dtype(target)?
}
Err(e) => return Err(e.into()),
} Prevention
- Call .contiguous() after transpose/slice before dtype conversion
- Cast tensors while they are still contiguous in the dataflow
- Keep GPU tensors in dtypes with full strided cast coverage (F32/F16/BF16)
When it happens
Trigger: Calling to_dtype on a non-contiguous Metal tensor (e.g. after transpose/slice/narrow) with a dtype pair absent from the strided cast table.
Common situations: Casting a transposed activation map to fp16 on Metal; converting slices of embedding tables; working with permuted tensors in inference graphs.
Related errors
- Metal contiguous to_dtype
- Metal strided unary not implemented
- convtr1d: shape mismatch on c_in
- Invalid where: different dtypes for values
- metal col2im1d not implemented
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/1c476b7edb92d869.
Report an issue: GitHub.
Appendix: source
Thrown at candle-core/src/metal_backend/mod.rs:650
(DType::I64, DType::BF16) => "cast_i64_bf16_strided",
(DType::I64, DType::F16) => "cast_i64_f16_strided",
(DType::I64, DType::U32) => "cast_i64_u32_strided",
(DType::I64, DType::U8) => "cast_i64_u8_strided",
(DType::U32, DType::BF16) => "cast_u32_bf16_strided",
(DType::U32, DType::F16) => "cast_u32_f16_strided",
(DType::U32, DType::F32) => "cast_u32_f32_strided",
(DType::U32, DType::I64) => "cast_u32_i64_strided",
(DType::U32, DType::U8) => "cast_u32_u8_strided",
(DType::U8, DType::BF16) => "cast_u8_bf16_strided",
(DType::U8, DType::F16) => "cast_u8_f16_strided",
(DType::U8, DType::F32) => "cast_u8_f32_strided",
(DType::U8, DType::I64) => "cast_u8_i64_strided",
(DType::U8, DType::U32) => "cast_u8_u32_strided",
(left, right) => {
crate::bail!("Metal strided to_dtype {left:?} {right:?} not implemented")
}
};
candle_metal_kernels::call_cast_strided(
&device.device,
&encoder,
&device.kernels,
kernel_name,
layout.dims(),
src,
layout.stride(),
&buffer,
)
.map_err(MetalError::from)?;
}
Ok(Self::new(buffer, device.clone(), el_count, dtype))
}
fn unary_impl<B: UnaryOpT>(&self, layout: &Layout) -> Result<Self> {View on GitHub (pinned to d5fee525bf)