huggingface/candle · error
unsupported const-set f64
Error message
unsupported const-set f64
What it means
Thrown by candle's Metal backend when a const_set (fill_) is attempted on an F64 tensor. The generated Metal const-set kernels cover F16, BF16, F32, I64, U32 and U8 only; 64-bit float is not among them, so the backend rejects the op rather than running a missing kernel. Note F64 is generally second-class on Metal GPUs.
Source
Thrown at candle-core/src/metal_backend/mod.rs:480
) -> Result<()> {
let device = self_.device();
let dtype = self_.dtype;
let shape = l.shape();
let el_count = shape.elem_count();
let encoder = device.command_encoder()?;
let dst = buffer_o(&self_.buffer, l, self_.dtype);
if l.is_contiguous() {
use candle_metal_kernels::unary::contiguous;
let kernel_name = match dtype {
DType::F16 => contiguous::const_set::HALF,
DType::BF16 => contiguous::const_set::BFLOAT,
DType::F32 => contiguous::const_set::FLOAT,
DType::I64 => contiguous::const_set::I64,
DType::U32 => contiguous::const_set::U32,
DType::U8 => contiguous::const_set::U8,
DType::F8E4M3 => crate::bail!("unsupported const-set f8e4m3"),
DType::F64 => crate::bail!("unsupported const-set f64"),
DType::F4
| DType::F6E2M3
| DType::F6E3M2
| DType::F8E8M0
| DType::I16
| DType::I32 => {
return Err(Error::UnsupportedDTypeForOp(dtype, "const-set").bt())
}
};
candle_metal_kernels::call_const_set_contiguous(
&device.device,
&encoder,
&device.kernels,
kernel_name,
dtype.size_in_bytes(),
el_count,
s,
dst,View on GitHub (pinned to d5fee525bf)
Solutions
- Use F32 instead of F64: create/fill in DType::F32 and convert downstream if needed.
- Fill the F64 tensor on CPU, then transfer to the Metal device with .to_device().
- Cast to F32 with to_dtype, fill on Metal, cast back (accepting precision loss) only if an F64 result is truly required.
- Run the operation on the CPU device instead of Metal for this step.
Example fix
// before let t = Tensor::zeros(shape, DType::F64, &metal_device)?; t.fill_(1.0f64)?; // unsupported const-set f64 // after let t = Tensor::zeros(shape, DType::F32, &metal_device)?; t.fill_(1.0f32)?;
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_fillable_on_metal(t: &candle_core::Tensor) -> Result<(), String> {
use candle_core::DType;
if t.device().is_metal() && t.dtype() == DType::F64 {
return Err("F64 const-set unsupported on Metal; use F32".into());
}
Ok(())
} Type guard
fn is_metal_safe_fill_dtype(d: candle_core::DType) -> bool {
use candle_core::DType::*;
!matches!(d, F64 | F8E4M3 | F4 | F6E2M3 | F6E3M2 | F8E8M0 | I16 | I32)
} Try / catch
let filled = match t.fill_(v_f64) {
Ok(t) => t,
Err(e) if e.to_string().contains("unsupported const-set f64") => {
let mut t32 = t.to_dtype(DType::F32, t.device())?;
t32.fill_(v_f64)?;
t32
}
Err(e) => return Err(e),
}; Prevention
- Default to F32 for GPU (Metal) tensors; reserve F64 for CPU paths.
- Check t.device() before choosing dtype in setup code.
- Add an assert on dtype in tensor-construction helpers.
- Test Metal pipelines for dtype-related failures in CI on macOS.
When it happens
Trigger: Calling Tensor::fill_ / const_set with a Scalar::F64 on a tensor living on a Metal device, for either contiguous (metal_backend/mod.rs:480) or strided (mod.rs:511) layouts.
Common situations: Porting CUDA/CPU code that uses f64 tensors to macOS/Metal; scientific-computing defaults that assume f64; filling a float64 tensor with a constant before downcasting; code paths where the dtype was accidentally left at f64.
Related errors
- unsupported const-set f8e4m3
- Metal contiguous to_dtype {left:?} {right:?} not implemented
- Metal strided to_dtype {left:?} {right:?} not implemented
- 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/d08482bac938fca7.
Report an issue: GitHub.