jax-ml/jax · error · ValueError
CSC must have ndim=2; got {shape=}
Error message
CSC must have ndim=2; got {shape=} What it means
The legacy CSC (compressed sparse column) format, like CSR, only supports 2D matrices; CSC._empty backs sparse.empty(format='csc') and sparse.eye(format='csc') and validates len(shape) == 2. Use BCOO or batched BCSR (with transposed semantics) for anything non-2D.
Source
Thrown at jax/experimental/sparse/csr.py:180
def dtype(self) -> np.dtype:
return self.data.dtype
def __init__(self, args, *, shape):
self.data, self.indices, self.indptr = map(jnp.asarray, args)
super().__init__(args, shape=shape)
@classmethod
def fromdense(cls, mat, *, nse=None, index_dtype=np.int32):
if nse is None:
nse = (mat != 0).sum()
return csr_fromdense(mat.T, nse=nse, index_dtype=index_dtype).T
@classmethod
def _empty(cls, shape, *, dtype=None, index_dtype='int32'):
"""Create an empty CSC instance. Public method is sparse.empty()."""
shape = tuple(shape)
if len(shape) != 2:
raise ValueError(f"CSC must have ndim=2; got {shape=}")
data = jnp.empty(0, dtype)
indices = jnp.empty(0, index_dtype)
indptr = jnp.zeros(shape[1] + 1, index_dtype)
return cls((data, indices, indptr), shape=shape)
@classmethod
def _eye(cls, N, M, k, *, dtype=None, index_dtype='int32'):
return CSR._eye(M, N, -k, dtype=dtype, index_dtype=index_dtype).T
def todense(self):
return csr_todense(self.T).T
def transpose(self, axes=None):
assert axes is None
return CSR((self.data, self.indices, self.indptr), shape=self.shape[::-1])
def __matmul__(self, other):
if isinstance(other, JAXSparse):View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Use format='bcoo' for arbitrary-dimensional sparse arrays
- For batched matrices, use BCSR (with transposed layout) or BCOO with n_batch
- Reshape to 2D if the legacy CSC API is required
Example fix
# before m = sparse.empty((2, 3, 4), format='csc') # ValueError # after m = sparse.empty((2, 3, 4), format='bcoo')
Defensive patterns
Strategy: validation
Validate before calling
assert len(tuple(shape)) == 2, 'CSC is 2D only; use bcoo'
Type guard
def csc_shape_ok(shape) -> bool:
return len(tuple(shape)) == 2 Try / catch
try:
m = sparse.empty(shape, format='csc')
except ValueError:
m = sparse.empty(shape, format='bcoo') Prevention
- Treat csc as 2D-only
- Default to bcoo/bcsr for anything batched
When it happens
Trigger: sparse.empty(shape, format='csc') or sparse.eye(..., format='csc') where len(shape) != 2, e.g. a 3D or 1D shape.
Common situations: Switching a 2D pipeline to batched tensors while keeping format='csc'; format chosen from a config string hitting CSC for non-matrix shapes.
Related errors
- Unsupported shape: {shape}
- data batch dimensions not compatible for {data.shape=}, {sha
- Invalid {data.shape=} for {nse=}, {n_batch=}, {n_dense=}
- indices batch dimensions not compatible for {indices.shape=}
- shape mismatch: {sparr.shape=} {a.shape=}
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/1937dcbe0f8068ee.
Report an issue: GitHub.