tracel-ai/burn · error

Scalar not supported for {dtype:?}

Error message

Scalar not supported for {dtype:?}

What it means

Scalar::new (crates/burn-std/src/element/scalar.rs:25-43) converts a value into a Scalar matching a target DType. It handles float (including QFloat), int, uint, and bool dtypes; any other DType — i.e. one that is none of float/int/uint/bool — falls into the final `unimplemented!("Scalar not supported for {dtype:?}")` panic. In practice this fires when the dtype is a quantized type not classified as QFloat-compatible for scalars or another non-scalar-representable dtype.

Source

Thrown at crates/burn-std/src/element/scalar.rs:41

    /// # Note
    /// [`QFloat`](DType::QFloat) scalars are represented as float for element-wise operations.
    pub fn new<E: ElementConversion>(value: E, dtype: &DType) -> Self {
        if dtype.is_float() | matches!(dtype, &DType::QFloat(_)) {
            Self::Float(value.elem())
        } else if dtype.is_int() {
            Self::Int(value.elem())
        } else if dtype.is_uint() {
            Self::UInt(value.elem())
        } else if dtype.is_bool() {
            match dtype {
                DType::Bool(BoolStore::Native) => Self::Bool(value.elem()),
                DType::Bool(BoolStore::U8) | DType::Bool(BoolStore::U32) => {
                    Self::UInt(value.elem())
                }
                _ => unreachable!(),
            }
        } else {
            unimplemented!("Scalar not supported for {dtype:?}")
        }
    }

    /// Converts and returns the converted element.
    pub fn elem<E: Element>(self) -> E {
        match self {
            Self::Float(x) => x.elem(),
            Self::Int(x) => x.elem(),
            Self::UInt(x) => x.elem(),
            Self::Bool(x) => x.elem(),
        }
    }

    /// Returns the exact integer value, if valid.
    pub fn try_as_integer(&self) -> Option<Self> {
        match self {
            Scalar::Float(x) => (x.floor() == *x).then(|| Self::Int(x.to_i64().unwrap())),
            Scalar::Int(_) | Scalar::UInt(_) => Some(*self),

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Dequantize the tensor to a plain float dtype before applying scalar operations.
  2. Pass scalars only to tensors with standard float/int/uint/bool dtypes.
  3. If you control the code, extend Scalar::new to map the dtype (e.g. treat QFloat like f32 per the documented note).
  4. Upgrade burn if the missing dtype coverage was fixed upstream.

Example fix

// before
let s = Scalar::new(2.0f32, &DType::QFloat(scheme)); // may panic depending on scheme
// after
let f_tensor = q_tensor.dequantize(); // DType::F32
let s = Scalar::new(2.0f32, &f_tensor.dtype());
Defensive patterns

Strategy: validation

Validate before calling

fn scalar_supported(dtype: &DType) -> bool {
    dtype.is_float()
        || dtype.is_int()
        || dtype.is_uint()
        || dtype.is_bool()
        || matches!(dtype, DType::QFloat(_))
}
assert!(scalar_supported(&dtype), "Scalar::new unsupported for {dtype:?}");

Type guard

fn accepts_scalar(dtype: &DType) -> bool {
    !matches!(dtype, DType::QFloat(_)) || true // narrow: only standard dtypes are safe in all versions
}

Try / catch

// Scalar::new panics; validate dtype before scalar ops
if scalar_supported(&tensor.dtype()) {
    let out = tensor + 2.0f32;
} else {
    let out = tensor.dequantize() + 2.0f32;
}

Prevention

When it happens

Trigger: Calling `Scalar::new(value, &dtype)` with a dtype for which `is_float()`, `is_int()`, `is_uint()`, and `is_bool()` are all false — e.g. a quantized DType variant not covered by the QFloat match arm (dependent on the DType enum in this version).

Common situations: Passing a quantized dtype (DType::QFloat with an unusual scheme) or a newly added dtype into scalar-creating APIs like tensor elementwise ops with a scalar argument (e.g. `tensor + scalar` dispatching through Scalar::new).

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/55b57f3c19d06f6f. Report an issue: GitHub.