huggingface/transformers · error · ValueError

Can only set a dictionary as `tp_plan`

Error message

Can only set a dictionary as `tp_plan`

What it means

The tp_plan setter on distributed model mixins only accepts a dict mapping module-name patterns (with '*' wildcards for repeated layers) to parallel styles, or None to clear the plan. Passing a string, list, or any other object raises immediately; each value is subsequently validated against ALL_PARALLEL_STYLES as well.

Source

Thrown at src/transformers/distributed/mixin.py:115

                )
            return self._ep_plan
        return self._tp_plan

    @property
    def fsdp_plan(self) -> dict[str, str]:
        return self._fsdp_plan

    @property
    def pp_plan(self) -> dict[str, tuple[str, str]]:
        return self._pp_plan

    @tp_plan.setter
    def tp_plan(self, plan: dict[str, str] | None):
        if plan is None:
            self._tp_plan = {}
            return
        if not isinstance(plan, dict):
            raise ValueError("Can only set a dictionary as `tp_plan`")

        for layer_pattern, parallel_style in plan.items():
            if parallel_style not in ALL_PARALLEL_STYLES:
                raise ValueError(
                    f"Unsupported tensor parallel style '{parallel_style}' for layer '{layer_pattern}'. "
                    f"Supported styles are {list(ALL_PARALLEL_STYLES.keys())}"
                )

        model_param_names = [name for name, _ in self.named_parameters()]
        for layer_pattern in plan.keys():
            regex_pattern = layer_pattern.replace("*", r"\d+")
            pattern_matched = False
            for param_name in model_param_names:
                if re.match(regex_pattern, param_name):
                    pattern_matched = True
                    break
            if not pattern_matched:
                warnings.warn(

View on GitHub (pinned to a597f97485)

Solutions

  1. Pass a dict: model.tp_plan = {'layers.*': 'colwise'} with keys as module patterns and values from ALL_PARALLEL_STYLES.
  2. Pass None to clear the plan instead of an empty string/list.
  3. Validate externally loaded plans: isinstance(plan, dict) and all values in the supported style set before assigning.

Example fix

# before
model.tp_plan = "colwise"  # raises ValueError

# after
model.tp_plan = {"model.layers.*": "colwise", "lm_head": "rowwise"}
Defensive patterns

Strategy: type-guard

Validate before calling

if plan is not None and not isinstance(plan, dict):
    raise TypeError(f"tp_plan must be a dict, got {type(plan).__name__}")

Type guard

def is_valid_tp_plan(plan) -> bool:
    from transformers.distributed import ALL_PARALLEL_STYLES
    return plan is None or (
        isinstance(plan, dict)
        and all(isinstance(k, str) for k in plan)
        and all(v in ALL_PARALLEL_STYLES for v in plan.values())
    )

Try / catch

try:
    model.tp_plan = plan
except ValueError as e:
    if "dictionary" in str(e) or "Unsupported tensor parallel style" in str(e):
        raise TypeError(f"invalid tp_plan {plan!r}: {e}") from e
    raise

Prevention

When it happens

Trigger: Assigning model.tp_plan = 'colwise' (string) or a list of patterns instead of a dict; deserializing a plan from YAML/JSON that parsed into a list; passing a plan built by string concatenation instead of a literal dict.

Common situations: Config-driven setups loading tp plans from files whose schema drifted; users assuming tp_plan takes a single style string applied globally; copy-paste between APIs with different plan formats.

Related errors


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