tracel-ai/burn · error

matmul: unsupported dtype {:?}

Error message

matmul: unsupported dtype {:?}

What it means

The public matmul entry point dispatches on the lhs tensor dtype and supports F32, F64, F16 and BF16 only. Any other dtype (integer dtypes, Bool, etc.) hits the panic arm. Integer matmul exists as a separate int_matmul function.

Source

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

    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, "matmul requires at least 2D tensors");
    assert!(rhs_rank >= 2, "matmul requires at least 2D tensors");

    // Check inner dimensions match: lhs[..., M, K] x rhs[..., K, N]
    let k_lhs = lhs_shape[lhs_rank - 1];
    let k_rhs = rhs_shape[rhs_rank - 2];
    assert_eq!(k_lhs, k_rhs, "matmul: inner dimensions must match");

    match lhs.dtype() {
        DType::F32 => matmul_gemm::<f32>(lhs, rhs),
        DType::F64 => matmul_gemm::<f64>(lhs, rhs),
        DType::F16 => matmul_gemm::<f16>(lhs, rhs),
        DType::BF16 => matmul_bf16(lhs, rhs),
        _ => panic!("matmul: unsupported dtype {:?}", lhs.dtype()),
    }
}

/// Extract 2D matrix strides from a tensor layout.
/// Returns (row_stride, col_stride) for the last two dimensions.
fn get_2d_strides(layout: &Layout) -> (isize, isize) {
    let strides = layout.strides();
    let ndim = strides.len();
    let row_stride = strides[ndim - 2];
    let col_stride = strides[ndim - 1];
    (row_stride, col_stride)
}

/// Compute broadcast batch dimensions for batched matmul.
/// Returns (broadcast_shape, lhs_strides, rhs_strides) where strides map
/// output batch index to input batch offset (in matrices).
fn broadcast_batch_dims(
    lhs_batch: &[usize],

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Cast the operands to a float dtype before matmul: a.cast::<f32>().matmul(b.cast::<f32>()).
  2. For true integer matmul, use the int tensor API (int_matmul supports I32/I64).
  3. Dequantize int8 weights to float before the linear layer.
  4. Assert both operands are float dtype at the model forward boundary.

Example fix

// before
let y = indices.matmul(weights); // indices are I64 -> panic
// after
let y = indices.cast::<f32>().matmul(weights); // or use int_matmul for integer results
Defensive patterns

Strategy: validation

Validate before calling

assert!(lhs.dtype().is_float() && rhs.dtype().is_float(), "matmul requires float tensors, got {:?} and {:?}", lhs.dtype(), rhs.dtype());

Type guard

fn is_float_tensor(t: &FlexTensor) -> bool { matches!(t.dtype(), DType::F32 | DType::F64 | DType::F16 | DType::BF16) }

Prevention

When it happens

Trigger: Calling Tensor::matmul on a Flex tensor with an integer dtype (I64/I32/U8/...) or Bool instead of a float dtype.

Common situations: Matmul on one-hot/boolean masks without casting; embedding-index tensors (int64) accidentally fed into a matmul; PyTorch port where torch.matmul handled int inputs; quantized (int8) weights used directly without a dequantize step.

Related errors


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