{"record":{"id":"67249080d273cfda","repo":"jax-ml/jax","slug":"input-z-must-be-square","errorCode":null,"errorMessage":"Input 'Z' must be square.","messagePattern":"Input 'Z' must be square\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/scipy/linalg.py","lineNumber":2331,"sourceCode":"     [ 0.    2.37 -0.88]]\n\n    By contrast, the complex form is truly upper-triangular:\n\n    >>> with jnp.printoptions(precision=2, suppress=True):\n    ...   print(Tc)\n    [[ 3.76+0.j    1.29-0.78j  2.02-0.5j ]\n     [ 0.  +0.j   -0.88+0.91j -2.02+0.j  ]\n     [ 0.  +0.j    0.  +0.j   -0.88-0.91j]]\n  \"\"\"\n  del check_finite  # unused\n\n  T_arr = jnp.asarray(T)\n  Z_arr = jnp.asarray(Z)\n\n  if T_arr.ndim < 2 or T_arr.shape[-1] != T_arr.shape[-2]:\n    raise ValueError(\"Input 'T' must be square.\")\n  if Z_arr.ndim < 2 or Z_arr.shape[-1] != Z_arr.shape[-2]:\n    raise ValueError(\"Input 'Z' must be square.\")\n  if T_arr.shape[-1] != Z_arr.shape[-1]:\n    raise ValueError(f\"Input array shapes must match: Z: {Z_arr.shape} vs. T: {T_arr.shape}\")\n\n  return jnp_vectorize.vectorize(\n      _rsf2csf_2d, signature=\"(n,n),(n,n)->(n,n),(n,n)\")(T_arr, Z_arr)\n\n@overload\ndef hessenberg(a: ArrayLike, *, calc_q: Literal[False], overwrite_a: bool = False,\n               check_finite: bool = True) -> Array: ...\n\n@overload\ndef hessenberg(a: ArrayLike, *, calc_q: Literal[True], overwrite_a: bool = False,\n               check_finite: bool = True) -> tuple[Array, Array]: ...\n\n\n@jit(static_argnames=('calc_q', 'check_finite', 'overwrite_a'))\ndef hessenberg(a: ArrayLike, *, calc_q: bool = False, overwrite_a: bool = False,\n               check_finite: bool = True) -> Array | tuple[Array, Array]:","sourceCodeStart":2313,"sourceCodeEnd":2349,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/scipy/linalg.py#L2313-L2349","documentation":"In rsf2csf, the unitary transformation matrix Z must also be square (ndim >= 2 and shape[-1] == shape[-2]), matching the Schur factor it accompanies. Non-square or lower-dimensional Z fails this check right after the T check.","triggerScenarios":"Passing a 1-D or rectangular Z (e.g. the Q from a reduced QR, or a flattened matrix) to rsf2csf.","commonSituations":"Using a compacted/thin factor from another decomposition instead of the full Schur vectors; accidental reshape or axis drop in batched code.","solutions":["Pass the full square Z from schur(a)","Verify Z.ndim >= 2 and Z.shape[-1] == Z.shape[-2] before calling","Regenerate Z with calc_q=True in schur rather than reconstructing a reduced basis"],"exampleFix":"# before\nT, Z = schur(a, calc_q=False)\nTc, Zc = rsf2csf(T, Z)  # Z is None -> fails earlier; or wrong Z shape\n# after\nT, Z = schur(a, calc_q=True)\nTc, Zc = rsf2csf(T, Z)","handlingStrategy":"validation","validationCode":"Z = jnp.asarray(Z)\nassert Z.ndim >= 2 and Z.shape[-1] == Z.shape[-2], f'Z must be square, got {Z.shape}'\nTc, Zc = rsf2csf(T, Z)","typeGuard":"def is_square_matrix(x) -> bool:\n    x = jnp.asarray(x)\n    return x.ndim >= 2 and x.shape[-1] == x.shape[-2]","tryCatchPattern":"try:\n    rsf2csf(T, Z)\nexcept ValueError as e:\n    if \"'Z' must be square\" in str(e):\n        T, Z = schur(A, calc_q=True); rsf2csf(T, Z)\n    else: raise","preventionTips":["Request Q from schur with calc_q=True rather than substituting another basis","Keep decomposition factors paired in a dataclass/tuple to avoid mismatches","Beware reduced/thin factors — rsf2csf needs the full square Z"],"tags":["jax","rsf2csf","schur-form","shape-validation"],"backgroundTag":"expected-square-matrix","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}