tracel-ai/burn · error

binary_op: unsupported dtype {:?}

Error message

binary_op: unsupported dtype {:?}

What it means

binary_op in burn-flex applies an elementwise float op by dispatching on dtype; it supports F32 (with a SIMD fast path), F64, F16 and BF16 (via f32 round-trip) and panics on anything else. Public and used by both user code and backward-pass ops like relu_backward, gelu_backward and sigmoid_backward, so a wrongly-typed gradient tensor will panic here too.

Source

Thrown at crates/burn-flex/src/ops/binary.rs:57

    F64Op: Fn(f64, f64) -> f64 + Copy,
{
    debug_assert_eq!(lhs.dtype(), rhs.dtype(), "binary_op: dtype mismatch");

    // Broadcast tensors to the same shape if needed
    let (lhs, rhs) = crate::ops::expand::broadcast_binary(lhs, rhs);

    let dtype = lhs.dtype();

    match dtype {
        DType::F32 => binary_op_f32(lhs, rhs, f32_op, simd_hint),
        DType::F64 => binary_op_typed(lhs, rhs, f64_op),
        DType::F16 => binary_op_typed(lhs, rhs, |a: f16, b: f16| {
            f16::from_f32(f32_op(a.to_f32(), b.to_f32()))
        }),
        DType::BF16 => binary_op_typed(lhs, rhs, |a: bf16, b: bf16| {
            bf16::from_f32(f32_op(a.to_f32(), b.to_f32()))
        }),
        _ => panic!("binary_op: unsupported dtype {:?}", dtype),
    }
}

/// Specialized binary operation for f32 with SIMD fast path.
#[cfg(feature = "simd")]
fn binary_op_f32<Op>(
    mut lhs: FlexTensor,
    mut rhs: FlexTensor,
    op: Op,
    simd_hint: Option<BinaryOp>,
) -> FlexTensor
where
    Op: Fn(f32, f32) -> f32,
{
    // In-place SIMD fast path: lhs unique contiguous at offset 0, rhs
    // contiguous (no broadcast).
    if let Some(simd_op) = simd_hint
        && lhs.is_unique()

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Cast both operands to the same float dtype before the op: a.cast(DType::F32).op(b.cast(DType::F32)).
  2. Fix the producing op so the tensor is float before it reaches the binary op or its backward.
  3. For masks, use float masks (mask.cast(DType::F32)) or a dedicated where/select op instead of arithmetic.

Example fix

// before
let y = x * mask; // x: F32, mask: Bool -> binary_op panic
// after
let y = x.mul(mask.cast(DType::F32));
Defensive patterns

Strategy: type-guard

Validate before calling

if lhs.dtype() != rhs.dtype() || !matches!(lhs.dtype(), DType::F32 | DType::F64 | DType::F16 | DType::BF16) {
    lhs = lhs.cast(DType::F32);
    rhs = rhs.cast(DType::F32);
}

Type guard

fn is_float_dtype(d: DType) -> bool {
    matches!(d, DType::F32 | DType::F64 | DType::F16 | DType::BF16)
}

Try / catch

let y = std::panic::catch_unwind(|| binary_add(lhs.clone(), rhs.clone()))
    .unwrap_or_else(|_| binary_add(lhs.cast(DType::F32), rhs.cast(DType::F32)));

Prevention

When it happens

Trigger: Any float binary op (add/sub/mul/div on float tensors) with a non-float dtype; backward passes (relu_backward, gelu_backward, sigmoid_backward, log_sigmoid_backward, prelu) receiving integer or bool tensors; test helper test_binary_add_f16 with an exotic dtype.

Common situations: Bool mask multiplied with float activations without casting; integer features fed into an activation with a float sibling; autodiff gradient produced with mismatched dtype; PyTorch-style implicit type promotion expectations that Rust burn does not perform.

Related errors


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