{"record":{"id":"1937dcbe0f8068ee","repo":"jax-ml/jax","slug":"csc-must-have-ndim-2-got-shape","errorCode":null,"errorMessage":"CSC must have ndim=2; got {shape=}","messagePattern":"CSC must have ndim=2; got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/experimental/sparse/csr.py","lineNumber":180,"sourceCode":"  def dtype(self) -> np.dtype:\n    return self.data.dtype\n\n  def __init__(self, args, *, shape):\n    self.data, self.indices, self.indptr = map(jnp.asarray, args)\n    super().__init__(args, shape=shape)\n\n  @classmethod\n  def fromdense(cls, mat, *, nse=None, index_dtype=np.int32):\n    if nse is None:\n      nse = (mat != 0).sum()\n    return csr_fromdense(mat.T, nse=nse, index_dtype=index_dtype).T\n\n  @classmethod\n  def _empty(cls, shape, *, dtype=None, index_dtype='int32'):\n    \"\"\"Create an empty CSC instance. Public method is sparse.empty().\"\"\"\n    shape = tuple(shape)\n    if len(shape) != 2:\n      raise ValueError(f\"CSC must have ndim=2; got {shape=}\")\n    data = jnp.empty(0, dtype)\n    indices = jnp.empty(0, index_dtype)\n    indptr = jnp.zeros(shape[1] + 1, index_dtype)\n    return cls((data, indices, indptr), shape=shape)\n\n  @classmethod\n  def _eye(cls, N, M, k, *, dtype=None, index_dtype='int32'):\n    return CSR._eye(M, N, -k, dtype=dtype, index_dtype=index_dtype).T\n\n  def todense(self):\n    return csr_todense(self.T).T\n\n  def transpose(self, axes=None):\n    assert axes is None\n    return CSR((self.data, self.indices, self.indptr), shape=self.shape[::-1])\n\n  def __matmul__(self, other):\n    if isinstance(other, JAXSparse):","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/experimental/sparse/csr.py#L162-L198","documentation":"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.","triggerScenarios":"sparse.empty(shape, format='csc') or sparse.eye(..., format='csc') where len(shape) != 2, e.g. a 3D or 1D shape.","commonSituations":"Switching a 2D pipeline to batched tensors while keeping format='csc'; format chosen from a config string hitting CSC for non-matrix shapes.","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"],"exampleFix":"# before\nm = sparse.empty((2, 3, 4), format='csc')  # ValueError\n\n# after\nm = sparse.empty((2, 3, 4), format='bcoo')","handlingStrategy":"validation","validationCode":"assert len(tuple(shape)) == 2, 'CSC is 2D only; use bcoo'","typeGuard":"def csc_shape_ok(shape) -> bool:\n    return len(tuple(shape)) == 2","tryCatchPattern":"try:\n    m = sparse.empty(shape, format='csc')\nexcept ValueError:\n    m = sparse.empty(shape, format='bcoo')","preventionTips":["Treat csc as 2D-only","Default to bcoo/bcsr for anything batched"],"tags":["jax","sparse","csc","shape-validation"],"backgroundTag":"sparse-format-dimension-mismatch","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}