jax-ml/jax · error · ValueError
must be a tuple of factors
Error message
{kind} must be a tuple of factors What it means
check_special_factors validates that reduction_factors, need_replication_factors, or permutation_factors is a tuple of factor names. A non-tuple (list, string, None where a tuple is expected) triggers this error.
Solutions
- Wrap the factors in a tuple: reduction_factors=('m',)
- Convert existing lists with tuple(...) before passing
Example fix
# before
reduction_factors = ['m']
# after
reduction_factors = ('m',) Defensive patterns
Strategy: type-guard
Validate before calling
assert isinstance(reduction_factors, tuple) and isinstance(need_replication_factors, tuple) and isinstance(permutation_factors, tuple)
Type guard
def is_factor_tuple(x) -> bool:
return isinstance(x, tuple) and all(isinstance(f, str) for f in x) Prevention
- Always use tuple literals ('m',) not lists or bare strings
- Lint calls with a wrapper that coerces tuple(x)
When it happens
Trigger: Passing reduction_factors=['m'] (a list) or a bare string 'm' instead of ('m',) to def_partition / str_to_sdy_sharding_rule.
Common situations: Using a list literal out of habit; passing a single factor as a string instead of a 1-tuple.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- : arrays must have same number of dimensions, got .
- Expected unreduced_kind to be of type…
- Expected unreduced_kind to be of type…
- factor_sizes must be a dict of str to int, but got
- argument of ManualAxisType should of type `frozenset` or…
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/7dc815cbbf7db401.
Report an issue: GitHub.
Appendix: source
Thrown at jax/_src/custom_partitioning_sharding_rule.py:163
f"Factor {factor} is not used in the rule, but size is provided")
# Check that factors that are used for a whole dimension aren't in
# factor_sizes and factors that are never used for a whole dimension are
# in factor_sizes.
for factor, inferable in factors_inferrable.items():
if factor not in factor_sizes and not inferable:
raise ValueError(
f"Factor {factor} is only used in compound factors; must specify"
" its size")
if factor in factor_sizes and inferable:
raise ValueError(
f"Factor {factor} represents a whole dimension; do not specify its"
" size")
special_factors = set()
def check_special_factors(kind, factors):
if not isinstance(factors, tuple):
raise ValueError(f"{kind} must be a tuple of factors")
if len(factors) != len(set(factors)):
raise ValueError(f"{kind} contains duplicated factors")
for factor in factors:
if factor not in factors_inferrable:
raise ValueError(
f"Factor {factor} in {kind} is not used in the rule")
if factor in special_factors:
raise ValueError(f"Factor {factor} can only be in one of the "
f"reduction, need replication, or permutation factor sets.")
special_factors.add(factor)
check_special_factors("reduction_factors", reduction_factors)
check_special_factors("need_replication_factors", need_replication_factors)
check_special_factors("permutation_factors", permutation_factors)
self.operand_mappings = operand_mappingsView on GitHub (pinned to 1e1c6a8fc0)