{"record":{"id":"5d6cf684d544c35b","repo":"keras-team/keras","slug":"incompatible-shapes-between-a-and-b-expected","errorCode":null,"errorMessage":"Incompatible shapes between `a` and `b`. Expected `a.shape[-2] == b.shape[-2]`. Received: a.shape={a.shape}, b.shape={b.shape}","messagePattern":"Incompatible shapes between `a` and `b`\\. Expected `a\\.shape\\[-2\\] == b\\.shape\\[-2\\]`\\. Received: a\\.shape=(.+?), b\\.shape=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/linalg.py","lineNumber":868,"sourceCode":"                \"Expected input to have rank >= 2. \"\n                f\"Received input with shape {a.shape}.\"\n            )\n\n\ndef _assert_square(*arrays):\n    for a in arrays:\n        m, n = a.shape[-2:]\n        if m != n:\n            raise ValueError(\n                \"Expected a square matrix. \"\n                f\"Received non-square input with shape {a.shape}\"\n            )\n\n\ndef _assert_a_b_compat(a, b):\n    if a.ndim == b.ndim:\n        if a.shape[-2] != b.shape[-2]:\n            raise ValueError(\n                \"Incompatible shapes between `a` and `b`. \"\n                \"Expected `a.shape[-2] == b.shape[-2]`. \"\n                f\"Received: a.shape={a.shape}, b.shape={b.shape}\"\n            )\n    elif a.ndim == b.ndim - 1:\n        if a.shape[-1] != b.shape[-1]:\n            raise ValueError(\n                \"Incompatible shapes between `a` and `b`. \"\n                \"Expected `a.shape[-1] == b.shape[-1]`. \"\n                f\"Received: a.shape={a.shape}, b.shape={b.shape}\"\n            )\n\n\nclass JVP(Operation):\n    def __init__(self, has_aux=False, *, name=None):\n        super().__init__(name=name)\n        self.has_aux = has_aux\n","sourceCodeStart":850,"sourceCodeEnd":886,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/linalg.py#L850-L886","documentation":"When a and b have the same rank, keras.ops.solve and keras.ops.solve_triangular require a.shape[-2] == b.shape[-2]: the number of equations (rows of the coefficient matrix) must match the rows of the right-hand side. _assert_a_b_compat raises this in the same-rank branch when the two matrix row counts disagree.","triggerScenarios":"Calling keras.ops.solve(A, b) with A of shape (3, 3) and b reshaped to (4, 1) or (2, 4, 1) vs A of (2, 3, 3); passing a stacked RHS whose per-batch row count differs from the stacked A; using solve_triangular after an LU/Cholesky factor where the RHS was sliced to a different length.","commonSituations":"Porting np.linalg.solve code where b of shape (n,) worked and the Keras reshape to (m, 1) introduced a mismatch; batched systems where A and b come from different data loaders with mismatched slicing; forgetting which axis of b is the row axis.","solutions":["Reshape b so its shape[-2] equals a.shape[-2]: for a single RHS use b.reshape(n, 1) where n == a.shape[-2].","In the batched case ensure both a and b carry the same leading batch dims and b's row axis matches a's row axis (a (B, n, n), b (B, n, k)).","Check that A and b were generated from the same number of equations; if b was sliced or padded differently, regenerate it consistently."],"exampleFix":"// before\nimport numpy as np\nfrom keras import ops\nA = np.random.rand(3, 3)\nb = np.random.rand(4)          # 4 RHS rows vs 3 equations\nx = ops.solve(A, b)            # ValueError\n\n// after\nA = np.random.rand(3, 3)\nb = np.random.rand(3)          # matches A's row count\nx = ops.solve(A, ops.reshape(b, (3, 1)))  # shape (3, 1) result","handlingStrategy":"validation","validationCode":"from keras import ops\n\ndef check_solve_same_rank(a, b):\n    if a.ndim == b.ndim:\n        sa, sb = ops.shape(a)[-2], ops.shape(b)[-2]\n        assert sa is None or sb is None or sa == sb, (\n            f\"a.shape[-2]={sa} != b.shape[-2]={sb}\")\n\ncheck_solve_same_rank(A, b)\nx = ops.solve(A, b)","typeGuard":"def rhs_matches_system(a, b) -> bool:\n    return a.ndim == b.ndim and (\n        a.shape[-2] is None or b.shape[-2] is None or a.shape[-2] == b.shape[-2]\n    )","tryCatchPattern":null,"preventionTips":["Write solver helpers that reshape b to (n, 1) internally.","Keep batched A and b produced by the same data pipeline stage.","Note np.linalg.solve has the same requirement — port its tests."],"tags":["keras","linalg","linear-solve","shape-validation","solver"],"backgroundTag":"tensor-rank-or-shape-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}