{"record":{"id":"dbb9767ac824e75e","repo":"hiyouga/LlamaFactory","slug":"cls-name-config-must-be-a-mapping-or-params","errorCode":null,"errorMessage":"{cls.__name__} config must be a mapping or {params_cls.__name__}, got {type(config).__name__}.","messagePattern":"(.+?) config must be a mapping or (.+?), got (.+?)\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/utils/plugin.py","lineNumber":83,"sourceCode":"        def decorator(obj: Any) -> Any:\n            cls._registry[self.name] = obj\n            return obj\n\n        return decorator\n\n    @classmethod\n    def parse_params(cls, config: Any, params_cls: type[ParamsT]) -> ParamsT:\n        \"\"\"Strictly convert config to the params dataclass used by one plugin entrypoint.\"\"\"\n        if not is_dataclass(params_cls):\n            raise TypeError(f\"{cls.__name__} params must be a dataclass type, got {params_cls!r}.\")\n        if isinstance(config, params_cls):\n            return config\n        if config is None:\n            values = {}\n        elif isinstance(config, dict):\n            values = dict(config)\n        else:\n            raise TypeError(\n                f\"{cls.__name__} config must be a mapping or {params_cls.__name__}, got {type(config).__name__}.\"\n            )\n\n        known = {item.name for item in fields(params_cls)}\n        unknown = set(values) - known\n        if unknown:\n            raise ValueError(\n                f\"Unknown params for {cls.__name__}.{params_cls.__name__}: {sorted(unknown)}. \"\n                f\"Expected: {sorted(known)}\"\n            )\n\n        return params_cls(**values)\n\n    def _resolve(self) -> Any:\n        cls = type(self)\n        if self.name is None:\n            raise ValueError(f\"{cls.__name__} must be constructed with a name.\")\n        if self.name not in cls._registry:","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/utils/plugin.py#L65-L101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nplugin.shard_model(model, dist_config=\"fsdp2\")\n\n# after\nplugin.shard_model(model, dist_config={\"name\": \"fsdp2\", \"ep_size\": 2})","handlingStrategy":"type-guard","validationCode":"assert dist_config is None or isinstance(dist_config, dict) or isinstance(dist_config, FSDP2Params), \\\n    f\"dist_config must be a mapping or params dataclass, got {type(dist_config).__name__}\"","typeGuard":"def is_plugin_config(config, params_cls) -> bool:\n    return config is None or isinstance(config, dict) or isinstance(config, params_cls)","tryCatchPattern":null,"preventionTips":["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."],"tags":["plugin","config","type-error","validation"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}