jax-ml/jax · error · ValueError

`unreduced_kind` should be `None` when `unreduced` is an emp

Error message

`unreduced_kind` should be `None` when `unreduced` is an empty set. Got {unreduced_kind=} and {unreduced=}

What it means

ManualAxisType validation: unreduced_kind only makes sense when there is at least one unreduced axis. If the unreduced set is empty, unreduced_kind must be None.

Source

Thrown at jax/_src/core.py:2359


def _check_mat(varying, unreduced, reduced, unreduced_kind):
  if varying & unreduced:
    raise ValueError(
        "varying and unreduced cannot have common mesh axes. Got"
        f" varying={varying} and unreduced={unreduced}")
  if varying & reduced:
    raise ValueError(
        "varying and reduced cannot have common mesh axes. Got"
        f" varying={varying} and reduced={reduced}")
  assert not (varying & unreduced & reduced)

  if unreduced_kind is not None and not isinstance(unreduced_kind, UnreducedKind):
    raise TypeError(
        "Expected unreduced_kind to be of type `jax.sharding.UnreducedKind`"
        f" but got {type(unreduced_kind)}")
  if not unreduced and unreduced_kind is not None:
    raise ValueError(
        "`unreduced_kind` should be `None` when `unreduced` is an empty set."
        f" Got {unreduced_kind=} and {unreduced=}")

def _canonicalize_mat(name, val):
  if not isinstance(val, frozenset):
    if not isinstance(val, set):
      raise TypeError(
          f"{name} argument of ManualAxisType should "
          f"of type `frozenset` or `set`. Got type {type(val)}")
    val = frozenset(val)
  return val


@immutable
class ManualAxisType:
  __slots__ = ('varying', 'unreduced', 'reduced', 'unreduced_kind',
               '__weakref__')

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Set unreduced_kind=None whenever unreduced is empty
  2. Guard: kind if unreduced else None
  3. Use the default constructor (kind defaults to None) unless needed

Example fix

// before
mat = ManualAxisType(unreduced=frozenset(), unreduced_kind=UnreducedKind.sum)

// after
mat = ManualAxisType(unreduced_kind=UnreducedKind.sum if unreduced else None)
Defensive patterns

Strategy: validation

Validate before calling

if not unreduced and unreduced_kind is not None:
    unreduced_kind = None

Type guard

def consistent(unreduced, kind): return (not unreduced and kind is None) or (bool(unreduced) and (kind is None or isinstance(kind, UnreducedKind)))

Prevention

When it happens

Trigger: ManualAxisType(unreduced=frozenset(), unreduced_kind=UnreducedKind.sum), or code that unconditionally passes a kind even when the unreduced set empties out.

Common situations: Generic code paths that always set unreduced_kind regardless of the sets; refactors that removed axes from 'unreduced' but kept the kind field.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/721ccfefc692d93a. Report an issue: GitHub.