{"record":{"id":"08320ac5e7429e68","repo":"jax-ml/jax","slug":"duplicate-axes-are-not-allowed-axes","errorCode":null,"errorMessage":"duplicate axes are not allowed: {axes=}","messagePattern":"duplicate axes are not allowed: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/numpy/hijax.py","lineNumber":207,"sourceCode":"  def __init__(\n      self,\n      a_aval: core.ShapedArray,\n      *fill_value_avals: core.ShapedArray,\n      size: int,\n      axes: tuple[int, ...],\n      out_dtype: np.dtype):\n    if core.is_symbolic_dim(size):\n      pass\n    else:\n      size = operator.index(size)\n      if size < 0:\n        raise ValueError(f\"size must be a positive integer; got {size=}\")\n    if not dtypes.issubdtype(out_dtype, np.integer):\n      raise ValueError(f\"out_dtype must be integer typed; got {out_dtype=}\")\n    if not all(0 <= ax < a_aval.ndim for ax in axes):\n      raise ValueError(f\"axes out of range for array with {a_aval.ndim} dimensions:  {axes=}\")\n    if len(axes) != len(set(axes)):\n      raise ValueError(f\"duplicate axes are not allowed: {axes=}\")\n    if fill_value_avals and len(fill_value_avals) != len(axes):\n      raise ValueError(f\"Expected {len(axes)} fill values, got {len(fill_value_avals)}\")\n    if any(fv.dtype != out_dtype for fv in fill_value_avals):\n      raise ValueError(f\"Expected fill values to have dtype {out_dtype}, got {fill_value_avals}\")\n    batch_shape = tuple(\n        s for i, s in enumerate(a_aval.shape) if i not in axes\n    )\n    for fv_aval in fill_value_avals:\n      try:\n        broadcasted = lax.broadcast_shapes(fv_aval.shape, batch_shape)\n      except ValueError as e:\n        raise ValueError(\n            f\"fill_value shape {fv_aval.shape} is not broadcast-compatible with \"\n            f\"batch shape {batch_shape}\"\n        ) from e\n      if broadcasted != batch_shape:\n        raise ValueError(\n            f\"fill_value shape {fv_aval.shape} cannot be broadcast to \"","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/numpy/hijax.py#L189-L225","documentation":"The fill-value index helper treats the axes tuple as a set of distinct array dimensions to index. The constructor fires when the same axis value appears more than once in axes, which would select the same dimension twice and is not a valid indexing.","triggerScenarios":"Constructing Nonzero(..., axes=(1, 1)) or building axes dynamically so the same axis appears twice, e.g. axes = (axis, axis).","commonSituations":"Programmatically composing axes lists that concatenate shared axes without deduplication.","solutions":["Deduplicate while preserving order: axes = tuple(dict.fromkeys(axes))","Review the code that builds the axes tuple for accidental repetition"],"exampleFix":"# before\naxes = (axis, axis)\n# after\naxes = (axis,)\n# or dedupe: axes = tuple(dict.fromkeys(axes))","handlingStrategy":"validation","validationCode":"assert len(axes) == len(set(axes)), axes","typeGuard":"def unique_axes(axes) -> bool:\n    return len(axes) == len(set(axes))","tryCatchPattern":null,"preventionTips":["Dedupe axes tuples built dynamically: tuple(dict.fromkeys(axes))","Keep axes constants in one place per module"],"tags":["jax","nonzero","axes","argument-validation"],"backgroundTag":"duplicate-axis","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}