huggingface/candle · error

Metal where_cond {left:?} {right:?} not implemented

Error message

Metal where_cond {left:?} {right:?} not implemented

What it means

Beyond matching branch dtypes, where_cond on Metal needs a kernel for the (condition-dtype, value-dtype) pair. Pairs outside the dispatch table (e.g. an I64 condition or unsupported combination) hit this bail, since no Metal kernel implements that selection.

Source

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

            .with_label("where")
            .build()?;
        let encoder = self.device.command_encoder()?;
        if t.dtype() != f.dtype() {
            crate::bail!(
                "Invalid where: different dtypes for values {:?} != {:?}",
                t.dtype(),
                f.dtype()
            );
        }
        let name = match (self.dtype, t.dtype()) {
            (DType::U8, DType::F32) => "where_u8_f32",
            (DType::U32, DType::F32) => "where_u32_f32",
            (DType::U8, DType::BF16) => "where_u8_bf16",
            (DType::U8, DType::F16) => "where_u8_f16",
            (DType::U8, DType::I64) => "where_u8_i64",
            (DType::U8, DType::U32) => "where_u8_u32",
            (DType::U8, DType::U8) => "where_u8_u8",
            (left, right) => crate::bail!("Metal where_cond {left:?} {right:?} not implemented"),
        };
        let src = buffer_o(&self.buffer, layout, self.dtype);
        let t = buffer_o(&t.buffer, t_l, t.dtype);
        let f = buffer_o(&f.buffer, f_l, f.dtype);
        candle_metal_kernels::call_where_cond(
            &device.device,
            &encoder,
            &device.kernels,
            name,
            dtype.size_in_bytes(),
            dims,
            src,
            layout.stride(),
            layout.is_contiguous(),
            t,
            t_l.stride(),
            t_l.is_contiguous(),
            f,

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Ensure the condition tensor is a supported dtype (U8/U32/F32 etc. per table) via to_dtype on the mask
  2. Align value-tensor dtype to a supported pair (F32 is broadly supported)
  3. Compute where_cond on CPU and move the result to Metal
  4. Upgrade candle for new Metal where_cond kernels

Example fix

// before
let out = mask_i64.where_cond(&a, &b)?; // i64 mask unsupported
// after
let out = mask_i64.to_dtype(DType::U8)?.where_cond(&a, &b)?;
Defensive patterns

Strategy: validation

Validate before calling

let mask = if matches!(mask.dtype(), DType::I64 | DType::F32) {
    mask.to_dtype(DType::U8)?
} else { mask };
if !matches!(a.dtype(), DType::F32 | DType::F16 | DType::BF16 | DType::U32 | DType::U8 | DType::I64) {
    anyhow::bail!("where_cond value dtype unsupported on Metal");
}

Try / catch

match mask.where_cond(&a, &b) {
    Ok(y) => y,
    Err(e) if e.to_string().contains("where_cond") && e.to_string().contains("not implemented") => {
        mask.to_dtype(DType::U8)?.where_cond(&a.to_dtype(DType::F32)?, &b.to_dtype(DType::F32)?)
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling where_cond on Metal with a condition/value dtype combination missing from the table, such as an I64 mask with F16 values, or U32 condition with BF16 values.

Common situations: Using comparison results (which may be U8/U32) with float tensors of unusual dtype; masks produced in one dtype and applied to tensors of another; porting CUDA-working code to Metal.

Related errors


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