huggingface/candle · error

Metal strided unary {name} {dtype:?} not implemented

Error message

Metal strided unary {name} {dtype:?} not implemented

What it means

Same as the contiguous case but for strided unary ops on Metal: the (name, dtype) lookup in the strided table fails and the library bails. Non-contiguous tensors (views from transpose/slice) require the strided kernel set, which has even narrower dtype coverage.

Source

Thrown at candle-core/src/metal_backend/mod.rs:816

                ("usin", DType::BF16) => strided::sin::BFLOAT,
                ("usqr", DType::BF16) => strided::sqr::BFLOAT,
                ("usqrt", DType::BF16) => strided::sqrt::BFLOAT,
                ("uneg", DType::BF16) => strided::neg::BFLOAT,
                ("uexp", DType::BF16) => strided::exp::BFLOAT,
                ("ulog", DType::BF16) => strided::log::BFLOAT,
                ("ugelu", DType::BF16) => strided::gelu::BFLOAT,
                ("ugelu_erf", DType::BF16) => strided::gelu_erf::BFLOAT,
                ("uerf", DType::BF16) => strided::erf::BFLOAT,
                ("usilu", DType::BF16) => strided::silu::BFLOAT,
                ("uabs", DType::BF16) => strided::abs::BFLOAT,
                ("uceil", DType::BF16) => strided::ceil::BFLOAT,
                ("ufloor", DType::BF16) => strided::floor::BFLOAT,
                ("urelu", DType::BF16) => strided::relu::BFLOAT,
                ("uround", DType::BF16) => strided::round::BFLOAT,
                ("utanh", DType::BF16) => strided::tanh::BFLOAT,

                (name, dtype) => {
                    crate::bail!("Metal strided unary {name} {dtype:?} not implemented")
                }
            };
            let dst = BufferOffset::zero_offset(&buffer);
            candle_metal_kernels::call_unary_strided(
                &device.device,
                &encoder,
                &device.kernels,
                kernel_name,
                layout.dims(),
                src,
                layout.stride(),
                dst,
            )
            .map_err(MetalError::from)?;
        }

        Ok(Self::new(buffer, device.clone(), el_count, dtype))
    }

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Call .contiguous() before the unary op so the contiguous kernel path is used
  2. Cast to a supported dtype (F32/F16/BF16) before the op
  3. Reorder ops so the unary op runs while the tensor is still contiguous
  4. Run the op on CPU

Example fix

// before
let y = x_t.floor()?; // x_t is a transposed f16 view on Metal
// after
let y = x_t.contiguous()?.floor()?;
Defensive patterns

Strategy: fallback

Validate before calling

if !t.is_contiguous() { t = t.contiguous()?; }
if !matches!(t.dtype(), DType::F32 | DType::F16 | DType::BF16) { t = t.to_dtype(DType::F32)?; }
let y = t.unary(op)?;

Try / catch

match t.unary(op) {
    Ok(y) => y,
    Err(e) if e.to_string().contains("strided unary") => t.contiguous()?.unary(op),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Applying a unary op to a non-contiguous Metal tensor whose (op, dtype) pair is not in the strided table, e.g. floor/round/tanh on strided integer tensors.

Common situations: Math on transposed or sliced activations in fp16/bf16 pipelines; rounding strided f32 tensors from custom sampling loops; integer strided views needing float ops.

Related errors


AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02). Data as JSON: /api/errors/e06aef10146faf95. Report an issue: GitHub.