huggingface/transformers · error · TypeError

Cannot flatten {type(obj).__name__} for pytree context

Error message

Cannot flatten {type(obj).__name__} for pytree context

What it means

The catch-all branch of _flatten_to_context: an object in the traced program's pytree context is not one of the supported types (None/bool/int/float/str, enum, tuple/list/set/frozenset, dict-like, or any object with __dict__). Types without __dict__ — e.g. classes using __slots__, C-extension types, complex tensors or numpy scalars — cannot be serialized into the export context and raise this TypeError naming the type.

Source

Thrown at src/transformers/exporters/exporter_dynamo.py:518

            "v": {k: _flatten_to_context(v, tensors) for k, v in obj.items()},
        }
    if isinstance(obj, (tuple, list, set, frozenset)):  # sequences/sets incl. NamedTuple
        return {
            "_t": "seq",
            "p": _class_to_path(cls),
            "v": [_flatten_to_context(i, tensors) for i in obj],
        }
    if isinstance(obj, types.MethodType):
        # A bound method can't be flattened into pytree context. Models shouldn't bind methods onto
        # objects they return at forward time (e.g. recurrent_gemma binds `get_seq_length`/
        # `get_mask_sizes` onto its `DynamicCache`) — that pattern isn't exportable; such a model is
        # skipped until the binding is refactored away (e.g. into a `Cache` subclass).
        raise TypeError("Cannot flatten a bound method for pytree context")
    if hasattr(obj, "__dict__"):
        state = {k: _flatten_to_context(v, tensors) for k, v in vars(obj).items()}
        return {"_t": "obj", "p": _class_to_path(cls), "s": state}

    raise TypeError(f"Cannot flatten {type(obj).__name__} for pytree context")


def _unflatten_from_context(ctx: Any, tensors: list) -> Any:
    """Reconstruct an object from its JSON-native context, substituting tensor index markers."""
    # --- Pure Python / JSON-native ---
    if ctx is None or type(ctx) in (bool, int, float, str):
        return ctx
    if type(ctx) is list:
        return [_unflatten_from_context(i, tensors) for i in ctx]
    if type(ctx) is dict and "_t" not in ctx:
        return {k: _unflatten_from_context(v, tensors) for k, v in ctx.items()}

    # --- Torch objects ---
    t = ctx["_t"]
    if t == "tensor":
        return tensors[ctx["i"]]
    if t == "layout":
        return getattr(torch, ctx["n"])

View on GitHub (pinned to a597f97485)

Solutions

  1. Convert the offending value to a supported type before export (int/float/str, tuple/list/dict, or a plain class with __dict__).
  2. If it is your class using __slots__, drop __slots__ or add a __dict__-carrying base so state can be captured.
  3. Keep numpy scalars out of module/config state — cast to Python builtins at model init.
  4. Locate the value first: the error names the type; grep your model for that type in attributes reachable from forward.

Example fix

# before (model code)
class WindowSpec:
    __slots__ = ("size", "stride")  # no __dict__ -> unflattenable

# after
class WindowSpec:  # plain class with __dict__
    def __init__(self, size, stride):
        self.size, self.stride = size, stride
Defensive patterns

Strategy: type-guard

Validate before calling

import types

SUPPORTED_PRIMITIVES = (type(None), bool, int, float, str)

def flattenable(obj) -> bool:
    if obj is None or isinstance(obj, SUPPORTED_PRIMITIVES):
        return True
    if isinstance(obj, (tuple, list, set, frozenset)):
        return all(flattenable(i) for i in obj)
    if isinstance(obj, types.MappingProxyType | dict):
        return all(flattenable(v) for v in obj.values())
    if hasattr(obj, "__dict__"):
        return all(flattenable(v) for v in vars(obj).values())
    return False

assert flattenable(model_state_reachable_from_forward), "non-serializable object would break export"

Type guard

def is_pytree_context_safe(obj) -> bool:
    return flattenable(obj)

Try / catch

try:
    DynamoExporter().export(model, inputs, cfg)
except TypeError as e:
    if "Cannot flatten" in str(e):
        # str(e) names the type — find and convert it in model state, then retry once
        bad = str(e).split("Cannot flatten")[1].split(" for pytree")[0].strip()
        raise RuntimeError(f"convert {bad} instances in model state to plain builtins/dataclasses") from e
    raise

Prevention

When it happens

Trigger: A model config/attribute reachable from the traced graph holds a slotted class, a numpy scalar, a complex number, or an extension object; the flattener walks it while building the JSON-native context for the ExportedProgram.

Common situations: Custom model code storing non-standard objects (slots-based dataclasses, numpy types, third-party C objects) in state that dynamo must capture; upgrading numpy/torch so a previously-tolerated type now takes the unsupported path.

Related errors


AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14). Data as JSON: /api/errors/4ce16539dc49d381. Report an issue: GitHub.