jax-ml/jax · error · TypeError
prevent_cse must be a bool or tuple of bools, got {type(prev
Error message
prevent_cse must be a bool or tuple of bools, got {type(prevent_cse)=} What it means
PyTreeDef::UnflattenImpl rebuilds a structure from a treedef and a list of leaves; when the traversal needs another leaf but the iterator is exhausted, it throws 'Too few leaves for PyTreeDef; expected %d, got %d'. num_leaves() is the treedef's expectation, leaf_count is what was supplied so far.
Source
Thrown at jax/_src/ad_checkpoint.py:380
@partial(jax.checkpoint, static_argnums=(1,))
def foo(x, y):
with jax.ensure_compile_time_eval():
y_pos = y > 0
if y_pos:
...
else:
...
As an alternative to using ``static_argnums`` (and
``jax.ensure_compile_time_eval``), it may be easier to compute some values
outside the :func:`jax.checkpoint`-decorated function and then close over them.
"""
if isinstance(static_argnums, int):
static_argnums = static_argnums,
if isinstance(prevent_cse, Sequence):
prevent_cse = tuple(prevent_cse)
if not isinstance(prevent_cse, (tuple, bool)):
raise TypeError("prevent_cse must be a bool or tuple of bools, got "
f"{type(prevent_cse)=}")
if config.remat3.value:
policy = None if policy is nothing_saveable else policy
return remat3(fun, policy=policy, static_argnums=static_argnums,
static_argnames=static_argnames, prevent_cse=prevent_cse)
@wraps(fun)
@api_boundary
def fun_remat(*args, **kwargs):
debug = api_util.debug_info(
"checkpoint / remat", fun,
args, kwargs, static_argnums=static_argnums)
fun_, args = _remat_static_argnums(fun, static_argnums, args)
args_flat, in_tree = tracing_registry.flatten((args, kwargs))
api_util.check_no_transformed_refs_args(lambda: debug, args_flat)
in_avals = [core.shaped_abstractify(x) for x in args_flat]
jaxpr, consts, out_tree = _trace_to_jaxpr(fun_, in_tree, tuple(in_avals), debug)View on GitHub (pinned to 1e1c6a8fc0)
Solutions
- Check len(leaves) == treedef.num_leaves before unflattening
- Flatten and unflatten with the same is_leaf predicate so treedef and leaves agree
- If you intentionally dropped leaves, use treedef.replace_like / jax.tree.map(None-safe) patterns instead of filtering the leaf list
- Log treedef.num_leaves vs len(leaves) at the call site when debugging
Example fix
# before leaves = [l for l in leaves if l is not None] out = treedef.unflatten(leaves) # ValueError: too few leaves # after assert len(leaves) == treedef.num_leaves, (len(leaves), treedef.num_leaves) out = treedef.unflatten(leaves)
Defensive patterns
Strategy: validation
Validate before calling
if len(leaves) != treedef.num_leaves:
raise ValueError(f'need {treedef.num_leaves} leaves, got {len(leaves)}')
out = treedef.unflatten(leaves) Try / catch
try:
out = treedef.unflatten(leaves)
except ValueError as e:
if 'Too few leaves' in str(e):
raise ValueError(f'leaf count mismatch: have {len(leaves)}, treedef wants {treedef.num_leaves}') from e
raise Prevention
- Always pair leaves and treedef from the same flatten call
- Use the same is_leaf on flatten and unflatten paths
- Assert num_leaves before unflattening in library code
When it happens
Trigger: Calling treedef.unflatten(leaves) or jax.tree.unflatten(treedef, leaves) with fewer leaves than treedef.num_leaves (e.g. passing a filtered or truncated leaf list, or leaves from a different treedef).
Common situations: Filtering leaves (e.g. dropping None or padding leaves) before unflattening; using leaves flattened under is_leaf but unflattening with the default treedef; mixing treedefs when batching/stacking params; vmap/pmap reshaping code that slices leaves.
Related errors
- the `static_argnums` argument to `jax.checkpoint` / `jax.rem
- numpy masked arrays are not supported as direct inputs to JA
- Python int {value} too large to convert to int64
- Python int {value} too large to convert to int32
- The names should be exclusive and should not intersect in `n
AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27).
Data as JSON: /api/errors/a14ef2f84a5892d1.
Report an issue: GitHub.