{"record":{"id":"6e2a4ec44ff9ca9d","repo":"keras-team/keras","slug":"the-last-dimension-of-inputs-to-cdist-must-match","errorCode":null,"errorMessage":"The last dimension of inputs to `cdist` must match. Received shapes: x.shape={x.shape}, y.shape={y.shape}","messagePattern":"The last dimension of inputs to `cdist` must match\\. Received shapes: x\\.shape=(.+?), y\\.shape=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/math.py","lineNumber":390,"sourceCode":"            y, -3\n        )\n        return backend.numpy.sqrt(\n            backend.numpy.sum(backend.numpy.square(diff), axis=-1)\n        )\n\n    def compute_output_spec(self, x, y):\n        if x.ndim < 2 or y.ndim < 2:\n            raise ValueError(\n                \"Inputs to `cdist` must have rank >= 2. \"\n                f\"Received shapes: x.shape={x.shape}, y.shape={y.shape}\"\n            )\n\n        if (\n            x.shape[-1] is not None\n            and y.shape[-1] is not None\n            and x.shape[-1] != y.shape[-1]\n        ):\n            raise ValueError(\n                \"The last dimension of inputs to `cdist` must match. \"\n                f\"Received shapes: x.shape={x.shape}, y.shape={y.shape}\"\n            )\n\n        try:\n            batch_shape = broadcast_shapes(x.shape[:-2], y.shape[:-2])\n        except ValueError:\n            raise ValueError(\n                \"Batch dimensions of inputs to `cdist` must be broadcastable. \"\n                f\"Received shapes: x.shape={x.shape}, y.shape={y.shape}\"\n            )\n\n        output_shape = tuple(batch_shape + [x.shape[-2], y.shape[-2]])\n        dtype = result_type(x.dtype, y.dtype, float)\n        return KerasTensor(shape=output_shape, dtype=dtype)\n\n\n@keras_export(\"keras.ops.cdist\")","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/math.py#L372-L408","documentation":"cdist computes distances between corresponding points, so the feature dimension (last axis) of x and y must match. Cdist.compute_output_spec raises this when both x.shape[-1] and y.shape[-1] are statically known and unequal.","triggerScenarios":"Calling keras.ops.cdist(x, y) with x of shape (N, 3) and y of shape (M, 2); comparing embeddings from two encoders with different output dims; forgetting to transpose coordinate arrays so the feature axis is not last.","commonSituations":"Two-branch Siamese/contrastive models whose towers have different output dims; mixing row-major vs column-major coordinate layouts; comparing a (T, D) time series against a (D, K) codebook transposed incorrectly.","solutions":["Project one side so feature dims match (a Dense layer, or pad/truncate to a common d), then call cdist.","Fix the layout: operands must be (..., n, d) with the same d; use ops.transpose if coordinates are axis-first.","Assert x.shape[-1] == y.shape[-1] before the call to fail with your own context."],"exampleFix":"// before\nfrom keras import ops\nx = ops.ones((10, 3))\ny = ops.ones((7, 2))\nd = ops.cdist(x, y)   # ValueError: 3 != 2\n\n// after\nx = ops.ones((10, 3))\ny = ops.pad(ops.ones((7, 2)), [[0, 0], [0, 1]])  # match feature dim\nd = ops.cdist(x, y)","handlingStrategy":"validation","validationCode":"from keras import ops\n\ndef assert_cdist_feature_match(x, y):\n    fx, fy = x.shape[-1], y.shape[-1]\n    assert fx is None or fy is None or fx == fy, (\n        f\"feature dims differ: {fx} vs {fy}\")\n\nassert_cdist_feature_match(x, y)\nd = ops.cdist(x, y)","typeGuard":"def cdist_features_match(x, y) -> bool:\n    a, b = x.shape[-1], y.shape[-1]\n    return a is None or b is None or a == b","tryCatchPattern":null,"preventionTips":["Check encoder output dims when comparing embeddings from two towers.","Keep coordinates in (..., n, d) layout everywhere.","Print shapes once at model build to lock the contract."],"tags":["keras","cdist","pairwise-distance","shape-validation","feature-dim"],"backgroundTag":"tensor-rank-or-shape-mismatch","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}