hiyouga/LlamaFactory · error · TypeError
{cls.__name__} config must be a mapping or {params_cls.__nam
Error message
{cls.__name__} config must be a mapping or {params_cls.__name__}, got {type(config).__name__}. What it means
TypeError from PluginBase.parse_params (plugin.py:83): the plugin config argument is neither None, a dict, nor an instance of the expected params dataclass, so it cannot be converted. Examples: passing a string, a list, a dataclass of the wrong type, or another plugin's params object. The check runs before field validation, so unknown-key errors (raised just below) never fire for these inputs.
Source
Thrown at src/llamafactory/v1/utils/plugin.py:83
def decorator(obj: Any) -> Any:
cls._registry[self.name] = obj
return obj
return decorator
@classmethod
def parse_params(cls, config: Any, params_cls: type[ParamsT]) -> ParamsT:
"""Strictly convert config to the params dataclass used by one plugin entrypoint."""
if not is_dataclass(params_cls):
raise TypeError(f"{cls.__name__} params must be a dataclass type, got {params_cls!r}.")
if isinstance(config, params_cls):
return config
if config is None:
values = {}
elif isinstance(config, dict):
values = dict(config)
else:
raise TypeError(
f"{cls.__name__} config must be a mapping or {params_cls.__name__}, got {type(config).__name__}."
)
known = {item.name for item in fields(params_cls)}
unknown = set(values) - known
if unknown:
raise ValueError(
f"Unknown params for {cls.__name__}.{params_cls.__name__}: {sorted(unknown)}. "
f"Expected: {sorted(known)}"
)
return params_cls(**values)
def _resolve(self) -> Any:
cls = type(self)
if self.name is None:
raise ValueError(f"{cls.__name__} must be constructed with a name.")
if self.name not in cls._registry:View on GitHub (pinned to f28afaf635)
Solutions
- Pass a dict of parameters (or None for defaults): DistributedPlugin.parse_params({'ep_size': 2}, FSDP2Params).
- Pass an instance of exactly the params_cls the entrypoint expects, not a sibling dataclass.
- If the config comes from YAML/JSON, ensure it deserializes to a mapping at the plugin-config level.
- For programmatic construction, keep types consistent: build params via parse_params rather than hand-instantiating foreign dataclasses.
Example fix
# before
plugin.shard_model(model, dist_config="fsdp2")
# after
plugin.shard_model(model, dist_config={"name": "fsdp2", "ep_size": 2}) Defensive patterns
Strategy: type-guard
Validate before calling
assert dist_config is None or isinstance(dist_config, dict) or isinstance(dist_config, FSDP2Params), \
f"dist_config must be a mapping or params dataclass, got {type(dist_config).__name__}" Type guard
def is_plugin_config(config, params_cls) -> bool:
return config is None or isinstance(config, dict) or isinstance(config, params_cls) Prevention
- Always pass plugin configs as plain dicts at API boundaries; let parse_params convert.
- Never feed one plugin's params object into another plugin's entrypoint.
When it happens
Trigger: Calling a plugin entrypoint with dist_config='fsdp2' (string name instead of a mapping), a FSDP2Params passed to a DeepSpeed plugin, or an object created by a different library version.
Common situations: Passing the plugin name string directly instead of {name: ..., ...}; reusing params objects across plugin families; configs loaded from YAML as lists instead of mappings; version skew where a persisted params dataclass no longer matches.
Related errors
- kernel_config.name must be a string.
- Unknown mixing strategy: {data_args.mix_strategy}.
- Cannot specify `val_size` if `eval_dataset` is not None.
- `kt_model_max_length` must be a positive integer.
- Cannot create new adapter upon a quantized model.
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/dbb9767ac824e75e.
Report an issue: GitHub.