{"record":{"id":"7973249136d4c43b","repo":"hiyouga/LlamaFactory","slug":"plugin-self-name-r-is-not-registered-under-cls","errorCode":null,"errorMessage":"Plugin {self.name!r} is not registered under {cls.__name__}.","messagePattern":"Plugin (.+?) is not registered under (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/utils/plugin.py","lineNumber":102,"sourceCode":"                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:\n            raise ValueError(f\"Plugin {self.name!r} is not registered under {cls.__name__}.\")\n        return cls._registry[self.name]\n\n    def __call__(self, *args, **kwargs) -> Any:\n        return self._resolve()(*args, **kwargs)\n\n    def __getattr__(self, attr: str) -> Any:\n        return getattr(self._resolve(), attr)\n","sourceCodeStart":84,"sourceCodeEnd":110,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/utils/plugin.py#L84-L110","documentation":"BasePlugin._resolve (src/llamafactory/v1/utils/plugin.py:102) looks up the plugin instance's name in its family's registry (cls._registry), a per-subclass dict populated only when the implementing module defining the @Plugin(\"name\").register() decorator is imported. If the name is absent — misspelled, never registered, or its defining module never imported/installed — resolution fails with this ValueError. Because BasePlugin routes both __call__ and __getattr__ through _resolve, the error can surface on the first attribute access or call of a plugin object, not just at construction.","triggerScenarios":"Constructing a plugin family member with a name that has no @register() decorator in the family's registry, e.g. PeftPlugin(\"lor\") (typo for \"lora\"), BatchingPlugin(\"dynamic\") (real names: padding_free, dynamic_batching, dynamic_padding_free), or QuantizationPlugin(\"gptq\") when only auto/bnb are registered. Also triggered when the plugin implementation lives in a module that was never imported (e.g. a KernelPlugin op in an optional NPU/CUDA kernels file that the import path skipped), or when code uses a fresh plugin family subclass whose registrations were never executed.","commonSituations":"Typo in a config string selecting a plugin (peft: \"lora\" misspelled, batching name mismatch with the registered set); optional kernels (liger_kernel, npu_fused_rope, cuda_fused_moe) not registered because the optional dependency or hardware-specific ops module was not imported; version upgrades that renamed or removed a registered name; custom plugins registered only at import time in a module the entry path does not import; copy-pasting a plugin name from v0 docs into a v1 (USE_V1=1) run.","solutions":["Check the exact registered names for the family: python -c \"from llamafactory.v1.plugins.model_plugins.peft import PeftPlugin; print(PeftPlugin._registry)\" (substitute the family you use) and correct the name in your config/code to one of those keys.","Ensure the module that registers the plugin is imported before resolution — for built-ins, import the family's package (e.g. llamafactory.v1.plugins.trainer_plugins.batching) or trigger the package's __init__ import path; for custom plugins, import your module before first use.","If using an optional kernel plugin (liger_kernel, npu_*, cuda_fused_moe), install the required dependency (e.g. liger-kernel) and confirm the ops module import succeeds — a swallowed ImportError earlier can leave the name unregistered.","When upgrading LlamaFactory, grep the new version's @XxxPlugin(\"...\").register() decorators for the family to see whether the name was renamed or dropped, then update your config."],"exampleFix":"# before — name typo, nothing registered under \"dynamic\"\nfrom llamafactory.v1.plugins.trainer_plugins.batching import BatchingPlugin\nstrategy = BatchingPlugin(\"dynamic\")\nbatch = strategy(...)\n\n# after — use an actually registered name\nstrategy = BatchingPlugin(\"dynamic_batching\")\nbatch = strategy(...)","handlingStrategy":"validation","validationCode":"def plugin_name_exists(plugin_cls, name: str) -> bool:\n    \"\"\"True when name is registered in this plugin family's registry.\"\"\"\n    return name in plugin_cls._registry\n\n\n# usage\nif not plugin_name_exists(BatchingPlugin, requested_name):\n    raise SystemExit(\n        f\"Unknown plugin {requested_name!r}; registered: {sorted(BatchingPlugin._registry)}\"\n    )","typeGuard":"def is_registered_plugin(plugin_cls, name: str) -> bool:\n    \"\"\"Narrow plugin names to those actually registered under plugin_cls.\"\"\"\n    return isinstance(name, str) and name in plugin_cls._registry","tryCatchPattern":"from llamafactory.v1.utils.plugin import BasePlugin\n\ntry:\n    result = plugin(*args)\nexcept ValueError as e:\n    if \"is not registered under\" in str(e):\n        raise SystemExit(\n            f\"{e}; available: {sorted(type(plugin)._registry)}\"\n        ) from None\n    raise","preventionTips":["Import the plugin family's package (which triggers all @register() decorators) before constructing or resolving any plugin.","Derive plugin names from plugin_cls._registry (or an explicit allowlist) rather than free-typed strings in YAML.","For optional kernel plugins, verify the optional dependency imports cleanly at startup — a failed import silently skips registration.","On upgrades, re-run a smoke check that prints sorted(FamilyPlugin._registry) and confirm every name in your config is present."],"tags":["plugin-registry","llamafactory","v1-plugins","import","config"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}