{"record":{"id":"bd997f552a89108f","repo":"jax-ml/jax","slug":"the-return-value-of-the-policies-should-be-a-boole","errorCode":null,"errorMessage":"The return value of the policies should be a boolean. Got: {out1} and {out2}. Please write a custom policy function directly, rather than using this helper function.","messagePattern":"The return value of the policies should be a boolean\\. Got: (.+?) and (.+?)\\. Please write a custom policy function directly, rather than using this helper function\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"jax/_src/ad_checkpoint.py","lineNumber":193,"sourceCode":"        \"The names should be exclusive and should not intersect in\"\n        \" `names_which_can_be_saved` and `names_which_can_be_offloaded`. Got\"\n        f\" names_which_can_be_saved={set(names_which_can_be_saved)},\"\n        f\" names_which_can_be_offloaded={set(names_which_can_be_offloaded)} and\"\n        f\" the intersection={set(intersection)}\")\n  return SaveAndOffloadOnlyTheseNames(\n      names_which_can_be_saved, names_which_can_be_offloaded,\n      offload_src, offload_dst)\n\n\ndef save_from_both_policies(policy_1, policy_2):\n  \"\"\"Logical OR of the given policies.\n\n  A residual is saveable iff it is saveable according to either policy.\"\"\"\n  def policy(prim, *args, **params):\n    out1 = policy_1(prim, *args, **params)\n    out2 = policy_2(prim, *args, **params)\n    if not (isinstance(out1, bool) and isinstance(out2, bool)):\n      raise ValueError(\n          \"The return value of the policies should be a boolean. Got:\"\n          f\" {out1} and {out2}. Please write a custom policy function directly,\"\n          \" rather than using this helper function.\")\n    return out1 or out2\n  return policy\n\n\n# Please update the file docs/gradient-checkpointing.md with any new\n# policies to keep the doc in sync.\ncheckpoint_policies = types.SimpleNamespace(\n    SaveOnlyTheseNames=SaveOnlyTheseNames,\n    SaveAnyNamesButThese=SaveAnyNamesButThese,\n    SaveAndOffloadOnlyTheseNames=SaveAndOffloadOnlyTheseNames,\n    everything_saveable=everything_saveable,\n    nothing_saveable=nothing_saveable,\n    dots_saveable=dots_saveable,\n    checkpoint_dots=dots_saveable,\n    dots_with_no_batch_dims_saveable=dots_with_no_batch_dims_saveable,","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/ad_checkpoint.py#L175-L211","documentation":"This is a DeprecationWarning (not yet an error) emitted when flattening encounters an object that is a Python iterable type unknown to the PyTree registry (e.g. a generator, set, frozenset, or custom __iter__ class). Such objects are currently treated as leaves, but a future JAX release will raise instead.","triggerScenarios":"Placing a set, generator, dict subclass, or custom iterable inside a structure passed to jax.tree.map / tree.flatten; because sets have no registered flatten rule, the C++ code warns and treats the whole iterable as one leaf.","commonSituations":"Passing {1,2,3} (a set) as a container, storing generators from comprehensions, migrating configs holding Python objects into JAX transforms; behavior change after upgrading JAX where previously it silently leaf-ified them.","solutions":["Convert sets to sorted lists: sorted(s); generators to lists: list(g)","Register the custom type with jax.tree_util.register_pytree_node if it should flatten","Pass is_leaf=lambda x: isinstance(x, (set, frozenset)) to explicitly opt into leaf treatment and silence the warning","Filter warnings with -W error::DeprecationWarning in CI to catch future breakage early"],"exampleFix":"# before\nparams = {'ids': {1, 2, 3}}\njax.tree.map(f, params)  # DeprecationWarning about iterable treated as leaf\n\n# after\nparams = {'ids': [1, 2, 3]}\njax.tree.map(f, params)","handlingStrategy":"validation","validationCode":"def no_unregistered_iterables(tree) -> bool:\n    bad = (set, frozenset, type((x for x in [])))\n    return not any(isinstance(l, bad) for l in jax.tree.leaves(tree))","typeGuard":"def is_leafable(x) -> bool:\n    return not isinstance(x, (set, frozenset))","tryCatchPattern":"try:\n    jax.tree.map(f, tree)\nexcept DeprecationWarning as w:\n    if 'treated as a leaf' in str(w):\n        tree = jax.tree.map(lambda s: sorted(s) if isinstance(s, (set, frozenset)) else s,\n                            tree, is_leaf=lambda x: isinstance(x, (set, frozenset)))","preventionTips":["Normalize sets/generators to lists before JAX transforms","Register custom containers with register_pytree_node","Run tests with -W error::DeprecationWarning to catch early"],"tags":["pytree","deprecation","sets","generators","jax"],"backgroundTag":"pytree-unknown-iterable-as-leaf","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}