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
- Regenerate/re-save the sparse arrays with the current JAX version instead of unpickling old ones
- If building aux_data manually, pass exactly {'shape': (n_rows, n_cols)}
- 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
- Version-pin JAX across serialization and deserialization environments
- Prefer sparse arrays' own save/load (e.g. store data/indices/indptr/shape explicitly) over pickling whole pytrees
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
- COO.tree_unflatten: invalid {aux_data=}
- CSR.tree_unflatten: invalid {aux_data=}
- CSC must have ndim=2; got {shape=}
- Malformed pytree proto (invalid node type)
- numpy masked arrays are not supported as direct inputs to JA
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/7d91f292b26d8513.
Report an issue: GitHub.