keras-team/keras · error · ValueError

LU decomposition failed: {e}. LU decomposition is only suppo

Error message

LU decomposition failed: {e}. LU decomposition is only supported for square matrices in Tensorflow.

What it means

lu_factor on the TensorFlow backend checks squareness explicitly because TF's LU implementation only supports square matrices; the underlying _assert_square ValueError is rewrapped with this backend-specific note. Non-square input works on JAX/NumPy backends but raises here on TensorFlow.

Source

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

    Returns:
        A tuple of two tensors: a tensor of shape `(..., M, M)` containing the
        lower and upper triangular matrices and a tensor of shape `(..., M)`
        containing the pivots.

    """
    if any_symbolic_tensors((x,)):
        return LuFactor().symbolic_call(x)
    return _lu_factor(x)


def _lu_factor(x):
    x = backend.convert_to_tensor(x)
    _assert_2d(x)
    if backend.backend() == "tensorflow":
        try:
            _assert_square(x)
        except ValueError as e:
            raise ValueError(
                f"LU decomposition failed: {e}. LU decomposition is only "
                "supported for square matrices in Tensorflow."
            )
    return backend.linalg.lu_factor(x)


class Norm(Operation):
    def __init__(self, ord=None, axis=None, keepdims=False, *, name=None):
        super().__init__(name=name)
        if isinstance(ord, str):
            if ord not in ("fro", "nuc"):
                raise ValueError(
                    "Invalid `ord` argument. "
                    "Expected one of {'fro', 'nuc'} when using string. "
                    f"Received: ord={ord}"
                )
        if isinstance(axis, int):
            axis = [axis]

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Pad or crop the matrix to square before lu_factor on the TF backend.
  2. Switch to a QR or SVD-based solve for non-square systems.
  3. Or run that computation on the numpy/jax backend if rectangular LU is required.

Example fix

# before
lu, p = keras.ops.linalg.lu_factor(A)  # A: (m, n), m != n, TF backend

# after
n = min(A.shape)
lu, p = keras.ops.linalg.lu_factor(A[:n, :n])
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np, keras
A = np.asarray(x)
if keras.backend.backend() == 'tensorflow':
    assert A.ndim == 2 and A.shape[0] == A.shape[1], 'TF lu_factor needs square input'

Type guard

def lu_factorizable(x, backend='tensorflow'):
    A = np.asarray(x)
    return A.ndim == 2 and (backend != 'tensorflow' or A.shape[0] == A.shape[1])

Try / catch

try:
    lu, p = keras.ops.linalg.lu_factor(A)
except ValueError as e:
    if 'only supported for square matrices' in str(e):
        n = min(A.shape)
        lu, p = keras.ops.linalg.lu_factor(A[:n, :n])
    else:
        raise

Prevention

When it happens

Trigger: keras.ops.linalg.lu_factor(rectangular_matrix) while backend() == 'tensorflow'; code that ran on JAX/NumPy with tall matrices then switched the keras backend to 'tensorflow'.

Common situations: Portable code written against JAX scipy.linalg.lu_factor semantics; solving least-squares-style systems on TF where a QR-based path is actually required.

Related errors


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