keras-team/keras · error · ValueError

Cholesky inverse failed: {e}

Error message

Cholesky inverse failed: {e}

What it means

cholesky_inverse validates the input then calls backend.linalg.cholesky_inverse; backend failures — most often a matrix that is not a valid Cholesky factor (not lower/upper triangular per the upper flag, or from a non-SPD source) — are re-raised under this wrapper message.

Source

Thrown at keras/src/ops/linalg.py:94

    Returns:
        A tensor of shape `(..., M, M)` representing the inverse of `x`.

    Raises:
        ValueError: If `x` is not a symmetric positive-definite matrix.
    """
    if any_symbolic_tensors((x,)):
        return CholeskyInverse(upper=upper).symbolic_call(x)
    return _cholesky_inverse(x, upper=upper)


def _cholesky_inverse(x, upper=False):
    x = backend.convert_to_tensor(x)
    _assert_2d(x)
    _assert_square(x)
    try:
        return backend.linalg.cholesky_inverse(x, upper=upper)
    except Exception as e:
        raise ValueError(f"Cholesky inverse failed: {e}")


class Det(Operation):
    def call(self, x):
        return _det(x)

    def compute_output_spec(self, x):
        _assert_2d(x)
        _assert_square(x)
        return KerasTensor(x.shape[:-2], x.dtype)


@keras_export(["keras.ops.det", "keras.ops.linalg.det"])
def det(x):
    """Computes the determinant of a square tensor.

    Args:
        x: Input tensor of shape `(..., M, M)`.

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Feed only genuine Cholesky factors; compute L = cholesky(x, upper=upper) and pass the same upper to cholesky_inverse.
  2. Symmetrize and jitter the source matrix before factorizing.
  3. If the input is triangular but from another library, transpose it when conventions differ.

Example fix

# before
L = scipy.linalg.cholesky(cov)          # upper by default
xinv = keras.ops.linalg.cholesky_inverse(L)  # expects lower

# after
xinv = keras.ops.linalg.cholesky_inverse(L, upper=True)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
X = np.asarray(x)
assert X.ndim == 2 and X.shape[0] == X.shape[1]
tri = np.triu(X) if upper else np.tril(X)
assert np.allclose(X, tri), 'input is not triangular for the given upper flag'

Type guard

def is_cholesky_factor(x, upper=False):
    X = np.asarray(x)
    if X.ndim != 2 or X.shape[0] != X.shape[1]:
        return False
    T = np.triu(X) if upper else np.tril(X)
    return np.allclose(X, T) and np.all(np.diag(T) > 0)

Try / catch

try:
    xinv = keras.ops.linalg.cholesky_inverse(L, upper=upper)
except ValueError as e:
    if 'Cholesky inverse failed' in str(e):
        L = keras.ops.linalg.cholesky(symmetrize(source), upper=upper)
        xinv = keras.ops.linalg.cholesky_inverse(L, upper=upper)
    else:
        raise

Prevention

When it happens

Trigger: keras.ops.linalg.cholesky_inverse(L) where L is a full (non-triangular) matrix; passing a Cholesky factor computed with upper=True but calling inverse with upper=False; factors from a non-SPD source matrix.

Common situations: Reconstructing covariance inverses from cached factors; mixing conventions between libraries (scipy.linalg.cholesky defaults to upper, numpy to lower).

Related errors


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/d147b2f4e034741f. Report an issue: GitHub.