{"record":{"id":"adc4c40e1da834a9","repo":"jax-ml/jax","slug":"argument-to-symmetric-eigendecomposition-must-have","errorCode":null,"errorMessage":"Argument to symmetric eigendecomposition must have shape [..., n, n], got shape {shape}","messagePattern":"Argument to symmetric eigendecomposition must have shape \\[\\.\\.\\., n, n\\], got shape (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/lax/linalg.py","lineNumber":1268,"sourceCode":"    tangent_out.append(dvl)\n  if compute_right_eigenvectors:\n    primal_out.append(vr)\n    tangent_out.append(dvr)\n  return primal_out, tangent_out\n\neig_p = linalg_primitive(\n    _eig_dtype_rule, (_float | _complex,), (2,), _eig_shape_rule, \"eig\",\n    multiple_results=True)\nad.primitive_jvps[eig_p] = eig_jvp_rule\nmlir.register_lowering(eig_p, _eig_cpu_lowering, platform=\"cpu\")\nregister_cpu_gpu_lowering(eig_p, _eig_gpu_lowering, (\"cuda\", \"rocm\", \"oneapi\"))\n\n\n# Symmetric/Hermitian eigendecomposition\n\ndef _eigh_shape_rule(shape, *, subset_by_index, **_):\n  if shape[0] != shape[-1]:\n    raise ValueError(\n        \"Argument to symmetric eigendecomposition must have shape [..., n, n], \"\n        f\"got shape {shape}\"\n    )\n  n = shape[0]\n  d = (n if subset_by_index is None else\n       subset_by_index[1] - subset_by_index[0])\n  return (n, d), (d,)\n\ndef _eigh_dtype_rule(dtype, **_):\n  return dtype, lax._complex_basetype(dtype)\n\ndef _eigh_cpu_gpu_lowering(\n    ctx, operand, *, lower, sort_eigenvalues, subset_by_index, algorithm,\n    target_name_prefix: str\n):\n  del sort_eigenvalues  # The CPU/GPU implementations always sort.\n  operand_aval, = ctx.avals_in\n  v_aval, w_aval = ctx.avals_out","sourceCodeStart":1250,"sourceCodeEnd":1286,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/lax/linalg.py#L1250-L1286","documentation":"jax/_src/lax/linalg.py:1268 in _eigh_shape_rule. eigh (symmetric/Hermitian eigendecomposition) only accepts square matrices: the last two dimensions of the operand must be equal (shape [..., n, n]). The rule compares shape[-2] != shape[-1] and reports the (unbatched) shape it sees.","triggerScenarios":"Calling jax.lax.linalg.eigh / jnp.linalg.eigh on a non-square array, e.g. shape (m, k) with m != k, or a batch of rectangular matrices; often from passing a covariance/correlation matrix that was miscomputed (e.g. X @ X.T with wrong axis) or flattening batch dims incorrectly.","commonSituations":"Feeding raw data (N x d) instead of the Gram/covariance (d x d); transposition bugs; ragged batches padded inconsistently; applying eigh where svd was intended.","solutions":["Verify a.shape[-2] == a.shape[-1] and construct the symmetric matrix properly (e.g. cov = X.T @ X or jnp.cov)","If you wanted singular values of a rectangular matrix, use jnp.linalg.svd instead","Add an assert before the call during development to catch shape mistakes early"],"exampleFix":"// before\nevals, evecs = jnp.linalg.eigh(X)  # X: (N, d) raw data\n// after\ncov = X.T @ X / (X.shape[0] - 1)  # (d, d)\nevals, evecs = jnp.linalg.eigh(cov)","handlingStrategy":"validation","validationCode":"assert a.shape[-2] == a.shape[-1], f'eigh needs square, got {a.shape}'","typeGuard":"def is_square(a: jax.Array) -> bool:\n    return a.ndim >= 2 and a.shape[-2] == a.shape[-1]","tryCatchPattern":null,"preventionTips":["Construct cov/Gram matrices explicitly before eigh","Use svd for rectangular data"],"tags":["jax","linalg","eigh","shape-validation","square-matrix"],"backgroundTag":"matrix-not-square","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}