huggingface/candle · error

{} is a dummy type and does not support operations

Error message

{} is a dummy type and does not support operations

What it means

Dummy types implement AddAssign by panicking: F6E2M3, F6E3M2, F4 and F8E8M0 are unimplemented placeholders and support no arithmetic. The impl exists only so generic code bounded by num-traits/std-ops compiles; executing += on them always aborts.

Source

Thrown at candle-core/src/dummy_dtype.rs:90

            fn cpu_storage_as_slice(_s: &crate::CpuStorage) -> Result<&[Self]> {
                Err(Error::UnsupportedDTypeForOp(DType::$dtype, "cpu_storage_as_slice").bt())
            }
        }
    };
}

dummy_with_dtype!(F6E2M3, F6E2M3);
dummy_with_dtype!(F6E3M2, F6E3M2);
dummy_with_dtype!(F4, F4);
dummy_with_dtype!(F8E8M0, F8E8M0);

// Implement NumAssign traits for dummy types
macro_rules! dummy_num_assign {
    ($ty:ty) => {
        impl std::ops::AddAssign for $ty {
            fn add_assign(&mut self, _other: Self) {
                panic!(
                    "{} is a dummy type and does not support operations",
                    stringify!($ty)
                )
            }
        }

        impl std::ops::SubAssign for $ty {
            fn sub_assign(&mut self, _other: Self) {
                panic!(
                    "{} is a dummy type and does not support operations",
                    stringify!($ty)
                )
            }
        }

        impl std::ops::MulAssign for $ty {
            fn mul_assign(&mut self, _other: Self) {
                panic!(

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Use a supported numeric element type (f32, f64, f16, bf16, i32, etc.) for arithmetic.
  2. Audit generic functions' type parameters so they are never instantiated with the dummy types.
  3. Convert dummy-dtype tensors to a supported dtype before reductions or element-wise ops.
  4. If MX formats are needed, implement real arithmetic in a candle fork rather than relying on these stubs.

Example fix

// before
let mut acc = F6E2M3; acc += x; // panics
// after
let mut acc = 0.0f32; acc += x; // accumulate in a supported type
Defensive patterns

Strategy: type-guard

Validate before calling

fn checked_add_assign<T: WithDType + AddAssign>(x: &mut T, y: T) -> Result<()> {
    if DUMMY.contains(&T::DTYPE) {
        return Err(Error::UnsupportedDTypeForOp(T::DTYPE, "add_assign").bt());
    }
    *x += y;
    Ok(())
}

Type guard

fn is_real_numeric<T: WithDType>(_v: &T) -> bool {
    !matches!(T::DTYPE, DType::F6E2M3 | DType::F6E3M2 | DType::F4 | DType::F8E8M0)
}

Try / catch

let r = std::panic::catch_unwind(|| { let mut a = F6E2M3; a += a; });
if r.is_err() { eprintln!("arithmetic on dummy dtype is unsupported"); }

Prevention

When it happens

Trigger: Using `x += y` where x has type F6E2M3/F6E3M2/F4/F8E8M0, or generic accumulation loops (sums, reductions, kernel loops bounded by Zero + AddAssign) instantiated over a dummy type.

Common situations: Generic numeric code (sums, reductions, kernel loops) instantiated over a dummy dtype instead of a real one; accidentally naming a dummy type as the element type parameter.

Related errors


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