jax-ml/jax · error · NotImplementedError

Left eigenvectors are not supported by cusolver

Error message

Left eigenvectors are not supported by cusolver

What it means

jax/_src/lax/linalg.py:1115 in _eig_gpu_lowering. The cusolver geev FFI path used by jax.lax.linalg.eig on GPU only computes right eigenvectors. If compute_left_eigenvectors=True is requested together with the cusolver implementation (explicitly or via auto-selection), JAX raises NotImplementedError because the underlying kernel has no left-eigenvector API.

Source

Thrown at jax/_src/lax/linalg.py:1115

  else:
    raise ValueError(f"Unsupported dtype: {dtype}")

  have_cusolver_geev = (
      target_name_prefix == "cu"
      and cuda_versions
      and cuda_versions.cusolver_get_version() >= 11701
  )

  if (
      implementation is None and have_cusolver_geev
      and not compute_left_eigenvectors
  ) or implementation == EigImplementation.CUSOLVER:
    if not have_cusolver_geev:
      raise RuntimeError(
          "Nonsymmetric eigendecomposition requires cusolver 11.7.1 or newer"
      )
    if compute_left_eigenvectors:
      raise NotImplementedError(
          "Left eigenvectors are not supported by cusolver")
    target_name = f"{target_name_prefix}solver_geev_ffi"
    avals_out = [
        ShapedArray(batch_dims + (n, n), dtype),
        ShapedArray(batch_dims + (n,), complex_dtype),
        ShapedArray(batch_dims + (n, n), dtype),
        ShapedArray(batch_dims + (n, n), dtype),
        ShapedArray(batch_dims, np.int32),
    ]

    rule = _linalg_ffi_lowering(target_name, avals_out=avals_out)
    _, w, vl, vr, info = rule(ctx, operand, left=compute_left_eigenvectors,
                              right=compute_right_eigenvectors)
    if is_real:
      unpack = mlir.lower_fun(_unpack_conjugate_pairs, multiple_results=False)
      if compute_left_eigenvectors:
        sub_ctx = ctx.replace(
            primitive=None,

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Request only right eigenvectors: compute_left_eigenvectors=False (the default)
  2. Derive left eigenvectors from right ones: for diagonalizable A, left vectors of A are right eigenvectors of A.T (rows of inv(V)); compute via eig(A.T) or Vinv = jnp.linalg.inv(v)
  3. Run that piece on CPU where a LAPACK path supports both, via jax.device_put + backend selection

Example fix

// before
wl, vl, vr = jax.lax.linalg.eig(a, compute_left_eigenvectors=True)
// after
w, vr = jax.lax.linalg.eig(a)  # left vectors: eig of transpose
wt, vl_t = jax.lax.linalg.eig(a.T)
vl = vl_t.T.conj()
Defensive patterns

Strategy: fallback

Validate before calling

want_left = False  # never request left eigenvectors on cusolver path
if want_left:
    plan = 'compute eig of A.T instead'

Try / catch

try:
    wl, vl, vr = jax.lax.linalg.eig(a, compute_left_eigenvectors=True)
except NotImplementedError:
    wt, vlt = jax.lax.linalg.eig(a.T)
    wl, vl = wt, vlt.T.conj()

Prevention

When it happens

Trigger: Calling jax.lax.linalg.eig(a, compute_left_eigenvectors=True, implementation=EigImplementation.CUSOLVER) on GPU; or compute_left_eigenvectors=True with implementation=None on a new cusolver when the auto path would pick cusolver.

Common situations: Porting scipy.linalg.eig(..., left=True, right=True) code to JAX; algorithm research code that wants both eigenvector sets on GPU.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/5dbaa084fa8debb3. Report an issue: GitHub.