huggingface/candle · error
Metal contiguous unary {name} {dtype:?} not implemented
Error message
Metal contiguous unary {name} {dtype:?} not implemented What it means
Metal contiguous unary ops (neg, exp, tanh, sign, etc.) are dispatched via a (op-name, dtype) kernel table. Requesting a unary op for a dtype without a matching Metal kernel hits this bail. Coverage is limited mostly to F32/F16/BF16 (and a few integer cases like sign on I64).
Source
Thrown at candle-core/src/metal_backend/mod.rs:743
("usilu", DType::BF16) => contiguous::silu::BFLOAT,
("usin", DType::F16) => contiguous::sin::HALF,
("usin", DType::F32) => contiguous::sin::FLOAT,
("usin", DType::BF16) => contiguous::sin::BFLOAT,
("usqr", DType::F16) => contiguous::sqr::HALF,
("usqr", DType::F32) => contiguous::sqr::FLOAT,
("usqr", DType::BF16) => contiguous::sqr::BFLOAT,
("usqrt", DType::F16) => contiguous::sqrt::HALF,
("usqrt", DType::F32) => contiguous::sqrt::FLOAT,
("usqrt", DType::BF16) => contiguous::sqrt::BFLOAT,
("utanh", DType::F16) => contiguous::tanh::HALF,
("utanh", DType::F32) => contiguous::tanh::FLOAT,
("utanh", DType::BF16) => contiguous::tanh::BFLOAT,
("usign", DType::F16) => contiguous::sign::HALF,
("usign", DType::F32) => contiguous::sign::FLOAT,
("usign", DType::BF16) => contiguous::sign::BFLOAT,
("usign", DType::I64) => contiguous::sign::I64,
(name, dtype) => {
crate::bail!("Metal contiguous unary {name} {dtype:?} not implemented")
}
};
candle_metal_kernels::call_unary_contiguous(
&device.device,
&encoder,
&device.kernels,
kernel_name,
dtype.size_in_bytes(),
el_count,
src,
&buffer,
)
.map_err(MetalError::from)?;
} else {
use candle_metal_kernels::unary::strided;
let kernel_name = match (B::KERNEL, dtype) {
("ucos", DType::F32) => strided::cos::FLOAT,View on GitHub (pinned to d5fee525bf)
Solutions
- Cast the tensor to F32 (or F16/BF16) before the unary op, cast back afterwards
- Perform the unary op on CPU for that tensor
- Use a dtype supported for that specific op on Metal
- Check candle_metal_kernels unary coverage and upgrade candle for newer kernels
Example fix
// before let y = x_i64.exp()?; // fails on Metal // after let y = x_i64.to_dtype(DType::F32)?.exp()?.to_dtype(DType::I64)?;
Defensive patterns
Strategy: fallback
Validate before calling
const METAL_UNARY_FLOAT_ONLY: [&str; 2] = ["exp", "log"]; // ops without integer kernels
let needs_float = METAL_UNARY_FLOAT_ONLY.contains(op_name);
if needs_float && !matches!(t.dtype(), DType::F32 | DType::F16 | DType::BF16) {
t = t.to_dtype(DType::F32)?;
} Try / catch
match t.unary(op) {
Ok(y) => y,
Err(e) if e.to_string().contains("unary") && e.to_string().contains("not implemented") => {
let orig = t.dtype();
t.to_dtype(DType::F32)?.unary(op)?.to_dtype(orig)?
}
Err(e) => return Err(e.into()),
} Prevention
- Cast integer tensors to float before math-heavy GPU sections
- Restrict Metal pipelines to F32/F16/BF16 for activations
- Test every op in your graph on the Metal backend before deployment
When it happens
Trigger: Applying any unary op (exp, log, sin, sqrt, sign, relu, ...) to a Metal tensor whose dtype lacks a kernel, e.g. u8::sqrt or i64::exp via the contiguous path.
Common situations: Integer tensors on Metal being passed through math ops; fp16 model running an op implemented only for f32; quantized/int8 tensors needing float-only math.
Related errors
- Metal strided unary {name} {dtype:?} not implemented
- Metal where_cond {left:?} {right:?} not implemented
- Metal conv1d {dtype:?} not implemented
- metal col2im1d {dtype:?} not implemented
- softmax-last-dim is not implemented for {dtype:?}
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/f30c375b0cd38395.
Report an issue: GitHub.