tracel-ai/burn · error

Dimensions are incompatible for matrix multiplication: LHS c

Error message

Dimensions are incompatible for matrix multiplication: LHS columns ({}) != ({})

What it means

For matrix multiplication the LHS's last dimension (columns) must equal the RHS's second-to-last dimension (rows). output_shape checks this when computing the result shape and panics when they differ.

Source

Thrown at crates/burn-ndarray/src/ops/matmul.rs:127

/// * If the matrix multiplication dimensions (last 2) are incompatible.
/// * If any other dimension is not the same for both tensors, or equal to 1. (Any dimension where
///   one dim is equal to 1 is broadcast.)
fn output_shape(lsh: &[usize], rsh: &[usize]) -> (Shape, Strides, Strides, Strides) {
    let ndims = lsh.num_dims();
    if ndims < 2 {
        panic!(
            "Matrix multiplication requires an array with at least 2 dimensions. Got Rank {}",
            ndims
        );
    }

    // Fetch matrix dimensions and check compatibility.
    let l_rows = lsh[ndims - 2];
    let l_cols = lsh[ndims - 1];
    let r_rows = rsh[ndims - 2];
    let r_cols = rsh[ndims - 1];
    if l_cols != r_rows {
        panic!(
            "Dimensions are incompatible for matrix multiplication: LHS columns ({}) != ({})",
            l_cols, r_rows
        );
    }
    // Set matrix dimensions of the output shape.
    let mut osh = vec![0; ndims];
    osh[ndims - 2] = l_rows;
    osh[ndims - 1] = r_cols;

    // Set other array dimensions, broadcasting as necessary.
    // Compute the strides inline.
    let mut cur_l_stride: usize = 1;
    let mut cur_r_stride: usize = 1;
    let mut cur_o_stride: usize = 1;
    let mut l_strides = Vec::with_capacity(ndims - 2);
    let mut r_strides = Vec::with_capacity(ndims - 2);
    let mut o_strides = Vec::with_capacity(ndims - 2);
    for i in (0..ndims - 2).rev() {

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Transpose the RHS: rhs.transpose() so its rows match the LHS columns.
  2. Fix the shapes so inner dimensions match (e.g. Linear layer weights should be [in_features, out_features] or transposed per the layer convention).
  3. Print both shapes before matmul and adjust reshape/permute accordingly.
  4. Check layer definitions/configs for swapped in/out feature sizes.

Example fix

// before: lhs [2,3], rhs [4,5]
let y = lhs.matmul(rhs); // panic 3 != 4
// after
let y = lhs.matmul(rhs.transpose()); // rhs now [5,4] -> still needs 3==5; correct fix:
// ensure rhs has shape [3,5], e.g. rhs = weight.transpose() when weight is [5,3]
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_matmul_inner_dims(lsh: &[usize], rsh: &[usize]) {
    assert!(lsh[lsh.len()-1] == rsh[rsh.len()-2],
        "matmul inner dims differ: {} vs {}", lsh[lsh.len()-1], rsh[rsh.len()-2]);
}

Prevention

When it happens

Trigger: Calling tensor.matmul(other) where lhs.shape()[last] != rhs.shape()[-2], e.g. matmul of [3,4] by [3,4] or [2,3] by [4,5] without transposing.

Common situations: Forgetting to transpose the weight matrix; mismatched feature counts between layers (in_features vs out_features); loading weights from a checkpoint with transposed layout.

Related errors


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