{"record":{"id":"5a3c437c3ed8cb57","repo":"huggingface/candle","slug":"only-2d-matrixes-are-supported-lhs-rhs","errorCode":null,"errorMessage":"only 2d matrixes are supported {lhs:?} {rhs:?}","messagePattern":"only 2d matrixes are supported (.+?) (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-core/src/shape.rs","lineNumber":234,"sourceCode":"                l_value\n            } else {\n                Err(Error::ShapeMismatchBinaryOp {\n                    lhs: lhs.clone(),\n                    rhs: rhs.clone(),\n                    op,\n                }\n                .bt())?\n            }\n        }\n        Ok(Shape::from(bcast_dims))\n    }\n\n    pub(crate) fn broadcast_shape_matmul(&self, rhs: &Self) -> Result<(Shape, Shape)> {\n        let lhs = self;\n        let lhs_dims = lhs.dims();\n        let rhs_dims = rhs.dims();\n        if lhs_dims.len() < 2 || rhs_dims.len() < 2 {\n            crate::bail!(\"only 2d matrixes are supported {lhs:?} {rhs:?}\")\n        }\n        let (m, lhs_k) = (lhs_dims[lhs_dims.len() - 2], lhs_dims[lhs_dims.len() - 1]);\n        let (rhs_k, n) = (rhs_dims[rhs_dims.len() - 2], rhs_dims[rhs_dims.len() - 1]);\n        if lhs_k != rhs_k {\n            crate::bail!(\"different inner dimensions in broadcast matmul {lhs:?} {rhs:?}\")\n        }\n\n        let lhs_b = Self::from(&lhs_dims[..lhs_dims.len() - 2]);\n        let rhs_b = Self::from(&rhs_dims[..rhs_dims.len() - 2]);\n        let bcast = lhs_b.broadcast_shape_binary_op(&rhs_b, \"broadcast_matmul\")?;\n        let bcast_dims = bcast.dims();\n\n        let bcast_lhs = [bcast_dims, &[m, lhs_k]].concat();\n        let bcast_rhs = [bcast_dims, &[rhs_k, n]].concat();\n        Ok((Shape::from(bcast_lhs), Shape::from(bcast_rhs)))\n    }\n}\n","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-core/src/shape.rs#L216-L252","documentation":"broadcast_shape_matmul computes output shapes for matmul with broadcasting. It requires both operands to have rank >= 2 because the last two dimensions are the matrix being multiplied; a 1-D or 0-D tensor has no matrix dimensions, so the op bails.","triggerScenarios":"Calling Tensor::matmul / broadcast_matmul where either the LHS or RHS tensor has fewer than 2 dimensions, e.g. matmul of a 1-D vector against a matrix without unsqueezing.","commonSituations":"Dot products written as a.matmul(&b) with a rank-1 tensor; squeezing a batch dimension away before matmul; passing scalars/vectors produced by sum/mean reductions directly into matmul.","solutions":["Promote 1-D tensors: use unsqueeze(0) on a vector-as-row or unsqueeze(1) for column, then squeeze the result","Use Tensor::dot for 1-D inner products instead of matmul","Check tensor ranks with .dims().len() before the op"],"exampleFix":"// before\nlet y = w.matmul(&x)?; // x is rank 1\n// after\nlet y = w.matmul(&x.unsqueeze(1)?)?.squeeze(1)?;","handlingStrategy":"validation","validationCode":"if lhs.dims().len() < 2 || rhs.dims().len() < 2 {\n    return Err(anyhow::anyhow!(\"matmul requires rank >= 2, got {:?} x {:?}\", lhs.dims(), rhs.dims()));\n}","typeGuard":null,"tryCatchPattern":"let y = match lhs.matmul(&rhs) {\n    Ok(y) => y,\n    Err(e) if e.to_string().contains(\"only 2d matrixes\") => {\n        let (a, b) = promote_to_2d(&lhs, &rhs)?;\n        a.matmul(&b)?\n    }\n    Err(e) => return Err(e.into()),\n};","preventionTips":["Check .dims().len() >= 2 before matmul; unsqueeze rank-1 tensors","Use Tensor::dot for vector dot products","Avoid squeezing dims you still need for matmul"],"tags":["candle","matmul","shape","rank"],"backgroundTag":"rank-mismatch-in-matmul","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}