huggingface/candle · error
Metal contiguous to_dtype {left:?} {right:?} not implemented
Error message
Metal contiguous to_dtype {left:?} {right:?} not implemented What it means
candle's Metal backend only implements a fixed table of dtype-pair casts for contiguous to_dtype operations; any (from,to) pair outside the table hits the catch-all bail arm. This means the requested dtype conversion has no Metal kernel available, so the library refuses rather than silently falling back. It is a backend-coverage limitation, not user data corruption.
Source
Thrown at candle-core/src/metal_backend/mod.rs:597
(DType::I64, DType::F16) => "cast_i64_f16",
(DType::I64, DType::F32) => "cast_i64_f32",
(DType::I64, DType::U32) => "cast_i64_u32",
(DType::I64, DType::U8) => "cast_i64_u8",
(DType::F16, DType::BF16) => "cast_f16_bf16",
(DType::F16, DType::F32) => "cast_f16_f32",
(DType::F16, DType::I64) => "cast_f16_i64",
(DType::F16, DType::U32) => "cast_f16_u32",
(DType::F16, DType::U8) => "cast_f16_u8",
(DType::BF16, DType::F16) => "cast_bf16_f16",
(DType::BF16, DType::F32) => "cast_bf16_f32",
(DType::BF16, DType::I64) => "cast_bf16_i64",
(DType::BF16, DType::U32) => "cast_bf16_u32",
(DType::BF16, DType::U8) => "cast_bf16_u8",
(left, right) => {
crate::bail!("Metal contiguous to_dtype {left:?} {right:?} not implemented")
}
};
candle_metal_kernels::call_cast_contiguous(
&device.device,
&encoder,
&device.kernels,
kernel_name,
self.dtype.size_in_bytes(),
el_count,
src,
&buffer,
)
.map_err(MetalError::from)?;
} else {
let kernel_name = match (self.dtype, dtype) {
(DType::BF16, DType::F16) => "cast_bf16_f16_strided",
(DType::BF16, DType::F32) => "cast_bf16_f32_strided",
(DType::BF16, DType::I64) => "cast_bf16_i64_strided",View on GitHub (pinned to d5fee525bf)
Solutions
- Cast on CPU first (tensor.to_device(&Device::Cpu)?.to_dtype(dtype)? then move back to Metal)
- Use a supported dtype pair from the cast table (F32/F16/BF16/U8/U32/I64 combos that are listed)
- Convert the tensor to F32 first, then to the target dtype, if both legs are supported
- Run the workload on the CUDA or CPU backend which has broader cast coverage
Example fix
// before let t = tensor.to_device(&metal_dev)?.to_dtype(DType::I64)?; // after let t = tensor.to_dtype(DType::I64)?; // CPU-side cast, then .to_device(&metal_dev)
Defensive patterns
Strategy: validation
Validate before calling
fn metal_cast_supported(from: candle_core::DType, to: candle_core::DType) -> bool {
use candle_core::DType::*;
matches!(
(from, to),
(F32, F16) | (F32, BF16) | (F32, I64) | (F32, U32) | (F32, U8)
| (F16, F32) | (BF16, F32) | (F16, BF16) | (BF16, F16)
// extend with the pairs your candle version's table lists
)
}
if !metal_cast_supported(t.dtype(), target) { t = t.to_device(&Device::Cpu)?.to_dtype(target)?.to_device(&metal_dev)?; } Try / catch
match tensor.to_dtype(target) {
Ok(t) => t,
Err(e) if e.to_string().contains("to_dtype") && e.to_string().contains("not implemented") => {
tensor.to_device(&Device::Cpu)?.to_dtype(target)?.to_device(&metal_dev)?
}
Err(e) => return Err(e.into()),
} Prevention
- Keep model activations in F32/F16/BF16 on Metal
- Do integer casts on CPU before moving to GPU
- Pin a candle version and verify its Metal kernel coverage for your dtype mix
When it happens
Trigger: Calling Tensor::to_dtype (or an op that casts internally) on a Metal device with a dtype pair not in the cast table, e.g. converting I64->F16, F32->I64 via the contiguous path, or any cast involving F64-style dtypes.
Common situations: Loading model weights stored in one dtype (e.g. i64 token ids) and casting to half precision for GPU inference; mixed-precision training pipelines converting between bf16 and integer types; dtype conversions that work on CPU but not on Metal.
Related errors
- Metal strided to_dtype {left:?} {right:?} not implemented
- unsupported const-set f8e4m3
- unsupported const-set f64
- Metal contiguous unary {name} {dtype:?} not implemented
- Metal strided unary {name} {dtype:?} not implemented
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/25a6d9f92ba14569.
Report an issue: GitHub.