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
- Transpose the RHS: rhs.transpose() so its rows match the LHS columns.
- Fix the shapes so inner dimensions match (e.g. Linear layer weights should be [in_features, out_features] or transposed per the layer convention).
- Print both shapes before matmul and adjust reshape/permute accordingly.
- 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
- Transposing weights once at load time avoids repeated transpose fixes.
- Verify Linear layer weight layouts (in_features x out_features) match backend convention.
- Log shapes of weights and activations at layer wiring time.
- Unit-test layer shapes with tiny tensors before full runs.
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
- Matrix multiplication requires an array with at least 2 dime
- Dimensions differ and cannot be broadcasted.
- Shape should be compatible shape={dim:?}: {err:?}
- NdArray supports arrays up to 6 dimensions, received: {}
- broadcast_shape: incompatible dimensions {} and {} at positi
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/22d1fbf2775fba35.
Report an issue: GitHub.