{"record":{"id":"06b04ff09426d196","repo":"jax-ml/jax","slug":"need-at-least-one-array-to-concatenate-06b04f","errorCode":null,"errorMessage":"Need at least one array to concatenate","messagePattern":"Need at least one array to concatenate","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/experimental/mosaic/gpu/fragmented_array.py","lineNumber":5340,"sourceCode":"  for i, dim in enumerate(src.shape):\n    if dim == 1 and dst.shape[dims[i]] > 1:\n      exp_indices.append(i)\n    if dim > 1:\n      pre_indices.append(i)\n  # If both exist, all expansions must happen before all preserved\n  # dimensions.\n  if exp_indices and pre_indices and max(exp_indices) >= min(pre_indices):\n    return False\n  return True\n\n\ndef concatenate(\n    arrays: Sequence[FragmentedArray],\n    axis: int = 0,\n) -> FragmentedArray:\n  \"\"\"Concatenates fragmented arrays along the specified axis.\"\"\"\n  if not arrays:\n    raise ValueError(\"Need at least one array to concatenate\")\n  arr0 = arrays[0]\n  rank = len(arr0.shape)\n  if not -rank <= axis < rank:\n    raise ValueError(f\"{axis=} is out of bounds for array of {rank=}\")\n  if axis < 0:\n    axis += rank\n\n  if len(arrays) == 1:\n    return arr0\n\n  new_shape = list(arr0.shape)\n  for i, arr in enumerate(arrays[1:], start=1):\n    if len(arr.shape) != rank:\n      raise ValueError(\n          f\"All arrays must have the same rank, got {len(arr.shape)} at index\"\n          f\" {i} (expected {rank})\"\n      )\n    if arr.mlir_dtype != arr0.mlir_dtype:","sourceCodeStart":5322,"sourceCodeEnd":5358,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/experimental/mosaic/gpu/fragmented_array.py#L5322-L5358","documentation":"FragmentedArray.concatenate validates that at least one array is passed, mirroring numpy.concatenate semantics. An empty sequence has no shape, dtype, or layout to infer a result from, so the library raises ValueError immediately.","triggerScenarios":"Calling FragmentedArray.concatenate([], axis=...) with an empty list/tuple, often because a list comprehension or accumulator produced zero arrays at runtime.","commonSituations":"Dynamic-length kernel pipelines where the number of arrays depends on runtime conditions (e.g., splitting work by number of tensor cores and getting 0); refactoring code that assumed a non-empty batch; passing an empty generator result.","solutions":["Guard the call: if not arrays: skip, return None, or construct a zero-length FragmentedArray explicitly.","Fix the upstream logic so the list is guaranteed non-empty (e.g., default to a single empty array)."],"exampleFix":"# before\nresult = FragmentedArray.concatenate(parts, axis=0)  # parts == []\n# after\nresult = (\n    FragmentedArray.concatenate(parts, axis=0)\n    if parts else None\n)","handlingStrategy":"validation","validationCode":"if not arrays:\n    return  # or build an explicit zero-length fragment\nresult = FragmentedArray.concatenate(arrays, axis=axis)","typeGuard":null,"tryCatchPattern":"try:\n    out = FragmentedArray.concatenate(parts, axis=0)\nexcept ValueError as e:\n    if 'at least one array' not in str(e): raise\n    out = None","preventionTips":["Treat empty parts lists as a no-op at the call site.","Assert len(parts) > 0 in debug builds.","Return early when accumulators are empty."],"tags":["jax","mosaic-gpu","validation","empty-input"],"backgroundTag":"empty-collection-argument","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}