tracel-ai/burn · error

int_matmul: unsupported dtype {:?}

Error message

int_matmul: unsupported dtype {:?}

What it means

int_matmul performs integer matrix multiplication but only supports I32 and I64 dtypes; the match panics for all others (I8/I16, unsigned U8..U64, floats, Bool). Operands must also share the same inner (K) dimension, enforced by an assert just above the panic.

Source

Thrown at crates/burn-flex/src/ops/matmul.rs:516

pub fn int_matmul(lhs: FlexTensor, rhs: FlexTensor) -> FlexTensor {
    assert_eq!(lhs.dtype(), rhs.dtype(), "int_matmul: dtype mismatch");

    let lhs_shape = lhs.layout().shape();
    let rhs_shape = rhs.layout().shape();
    let lhs_rank = lhs_shape.num_dims();
    let rhs_rank = rhs_shape.num_dims();

    assert!(lhs_rank >= 2, "int_matmul requires at least 2D tensors");
    assert!(rhs_rank >= 2, "int_matmul requires at least 2D tensors");

    let k_lhs = lhs_shape[lhs_rank - 1];
    let k_rhs = rhs_shape[rhs_rank - 2];
    assert_eq!(k_lhs, k_rhs, "int_matmul: inner dimensions must match");

    match lhs.dtype() {
        DType::I32 => matmul_i32(lhs, rhs),
        DType::I64 => matmul_i64(lhs, rhs),
        _ => panic!("int_matmul: unsupported dtype {:?}", lhs.dtype()),
    }
}

/// i32 matmul using naive triple loop with SIMD dot product.
fn matmul_i32(lhs: FlexTensor, rhs: FlexTensor) -> FlexTensor {
    let lhs = lhs.to_contiguous();
    let rhs = rhs.to_contiguous();

    let lhs_shape = lhs.layout().shape();
    let rhs_shape = rhs.layout().shape();
    let lhs_rank = lhs_shape.num_dims();
    let rhs_rank = rhs_shape.num_dims();

    if lhs_rank == 2 && rhs_rank == 2 {
        matmul_2d_i32(&lhs, &rhs)
    } else {
        matmul_batched_i32(lhs, rhs)
    }

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Cast both operands to I32 or I64 before the matmul: a.cast::<i32>().matmul(b.cast::<i32>()).
  2. For int8 quantized workloads, upcast to i32 (standard practice to avoid accumulation overflow anyway).
  3. For float tensors, use the float matmul path instead of int_matmul.
  4. Add a dtype assert on both operands before entering the matmul helper.

Example fix

// before
let out = w_u8.matmul(x_u8); // U8 -> panic
// after
let out = w_u8.cast::<i32>().matmul(x_u8.cast::<i32>());
Defensive patterns

Strategy: validation

Validate before calling

assert!(matches!(lhs.dtype(), DType::I32 | DType::I64) && matches!(rhs.dtype(), DType::I32 | DType::I64), "int_matmul supports only I32/I64, got {:?} and {:?}", lhs.dtype(), rhs.dtype());

Type guard

fn is_int_matmul_compatible(t: &FlexTensor) -> bool { matches!(t.dtype(), DType::I32 | DType::I64) }

Prevention

When it happens

Trigger: Calling int matmul with operands of dtype I8/I16 or any unsigned dtype (U8/U16/U32/U64), or passing float tensors to the int matmul path.

Common situations: Quantized inference with int8 weights/activations; image tensors (u8) fed into an integer linear layer; dtype mismatch between lhs (i32) and rhs (u8) so lhs itself is fine but patterns like casting only one operand mislead; porting numpy int matmuls with 16-bit types.

Related errors


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