tracel-ai/burn · error

Matrix multiplication requires an array with at least 2 dime

Error message

Matrix multiplication requires an array with at least 2 dimensions. Got Rank {}

What it means

output_shape computes the result shape for matmul and requires at least 2 dimensions because matrix multiplication operates on the last two axes. If the left-hand shape has rank < 2 the op cannot proceed and panics.

Source

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

    }
}

/// Compute the (broadcasted) output shape of matrix multiplication, along with strides for
/// the non-matrix dimensions of all arrays.
///
/// # Arguments
/// * `lsh`: Shape of the first (left-hand) matrix multiplication argument.
/// * `rsh`: Shape of the second (right-hand) matrix multiplication argument.
///
/// # Panics
/// * If `D` is not at least 2.
/// * 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];

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Unsqueeze the 1-D tensor to 2-D before matmul: vector.unsqueeze::<2>(0) for row-vector or unsqueeze::<2>(1) for column-vector.
  2. Use reshape to give the tensor at least 2 dimensions with compatible matrix dims.
  3. Verify the LHS rank before matmul with tensor.shape().num_dims() >= 2.
  4. If multiplying matrix by vector, use matmul with the vector expanded, or a dedicated mul/add instead.

Example fix

// before
let v = Tensor::<NdArray<f32>, 1>::from_floats([1.0, 2.0]);
let y = m.matmul(v); // panic: rank 1
// after
let v2 = v.unsqueeze::<2>(); // shape [1, 2]
let y = m.matmul(v2).squeeze::<1>(0);
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_rank_at_least2<D: burn::tensor::Dimension>(t: &burn::tensor::Tensor<burn::backend::NdArray, D>) {
    assert!(D::NUM_DIMS >= 2, "matmul requires rank >= 2, got {}", D::NUM_DIMS);
}

Try / catch

// burn panics rather than returning Result; run risky ops behind catch_unwind if needed
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| lhs.matmul(rhs.clone())));

Prevention

When it happens

Trigger: Calling tensor.matmul(other) with a rank-0 (scalar) or rank-1 (vector) LHS tensor. burn requires explicit unsqueeze/reshape to 2D+ before matmul.

Common situations: Passing a 1-D bias or flattened vector directly into matmul; a reshape/squeeze earlier in the pipeline accidentally dropped a batch dimension.

Related errors


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