jax-ml/jax · error · ValueError

CSC.tree_unflatten: invalid {aux_data=}

Error message

CSC.tree_unflatten: invalid {aux_data=}

What it means

JAX's CSC (compressed sparse column) array is a pytree; when it is unflattened (e.g. across jit/pmap boundaries, pickling, or tree_map), the auxiliary data must contain exactly the key 'shape'. If any other aux data is present, tree_unflatten rejects it as corrupt or incompatible.

Source

Thrown at jax/experimental/sparse/csr.py:219

    data, other = promote_dtypes(self.data, other)
    if other.ndim == 1:
      return _csr_matvec(data, self.indices, self.indptr, other,
                         shape=self.shape[::-1], transpose=True)
    elif other.ndim == 2:
      return _csr_matmat(data, self.indices, self.indptr, other,
                         shape=self.shape[::-1], transpose=True)
    else:
      raise NotImplementedError(f"matmul with object of shape {other.shape}")

  def tree_flatten(self):
    return (self.data, self.indices, self.indptr), {"shape": self.shape}

  @classmethod
  def tree_unflatten(cls, aux_data, children):
    obj = object.__new__(cls)
    obj.data, obj.indices, obj.indptr = children
    if aux_data.keys() != {'shape'}:
      raise ValueError(f"CSC.tree_unflatten: invalid {aux_data=}")
    obj.__dict__.update(**aux_data)
    return obj


#--------------------------------------------------------------------
# csr_todense

csr_todense_p = core.Primitive('csr_todense')

def csr_todense(mat: CSR) -> Array:
  """Convert a CSR-format sparse matrix to a dense matrix.

  Args:
    mat : CSR matrix
  Returns:
    mat_dense: dense version of ``mat``
  """
  return _csr_todense(mat.data, mat.indices, mat.indptr, shape=mat.shape)

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Regenerate/re-save the sparse arrays with the current JAX version instead of unpickling old ones
  2. If building aux_data manually, pass exactly {'shape': (n_rows, n_cols)}
  3. Check that data, indices, indptr children order matches the CSC layout

Example fix

// before
aux = {'shape': (3, 4), 'nse': 5}  # extra key -> error
CSC.tree_unflatten(aux, (data, indices, indptr))
// after
aux = {'shape': (3, 4)}
CSC.tree_unflatten(aux, (data, indices, indptr))
Defensive patterns

Strategy: validation

Validate before calling

assert set(aux.keys()) == {'shape'}, f'bad aux keys: {aux.keys()}'

Type guard

def is_valid_csc_aux(aux) -> bool:
    return isinstance(aux, dict) and set(aux.keys()) == {'shape'} and isinstance(aux['shape'], tuple)

Try / catch

try:
    obj = CSC.tree_unflatten(aux, children)
except ValueError as e:
    if 'tree_unflatten' in str(e):
        raise RuntimeError('Corrupt/incompatible CSC pytree data; re-save with current JAX') from e
    raise

Prevention

When it happens

Trigger: Reconstructing a jax.experimental.sparse.CSC from flattened children with aux_data whose keys are not exactly {'shape'}; typically from stale serialized/pickled objects from an older JAX version or manual tree manipulation.

Common situations: Unpickling CSC arrays saved by a different JAX version whose pytree layout changed; custom pytree plumbing that constructs aux_data dicts.

Related errors


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