hiyouga/LlamaFactory · error · ValueError

Plugin {self.name!r} is not registered under {cls.__name__}.

Error message

Plugin {self.name!r} is not registered under {cls.__name__}.

What it means

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.

Source

Thrown at src/llamafactory/v1/utils/plugin.py:102

                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:
            raise ValueError(f"Plugin {self.name!r} is not registered under {cls.__name__}.")
        return cls._registry[self.name]

    def __call__(self, *args, **kwargs) -> Any:
        return self._resolve()(*args, **kwargs)

    def __getattr__(self, attr: str) -> Any:
        return getattr(self._resolve(), attr)

View on GitHub (pinned to f28afaf635)

Solutions

  1. 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.
  2. 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.
  3. 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.
  4. 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.

Example fix

# before — name typo, nothing registered under "dynamic"
from llamafactory.v1.plugins.trainer_plugins.batching import BatchingPlugin
strategy = BatchingPlugin("dynamic")
batch = strategy(...)

# after — use an actually registered name
strategy = BatchingPlugin("dynamic_batching")
batch = strategy(...)
Defensive patterns

Strategy: validation

Validate before calling

def plugin_name_exists(plugin_cls, name: str) -> bool:
    """True when name is registered in this plugin family's registry."""
    return name in plugin_cls._registry


# usage
if not plugin_name_exists(BatchingPlugin, requested_name):
    raise SystemExit(
        f"Unknown plugin {requested_name!r}; registered: {sorted(BatchingPlugin._registry)}"
    )

Type guard

def is_registered_plugin(plugin_cls, name: str) -> bool:
    """Narrow plugin names to those actually registered under plugin_cls."""
    return isinstance(name, str) and name in plugin_cls._registry

Try / catch

from llamafactory.v1.utils.plugin import BasePlugin

try:
    result = plugin(*args)
except ValueError as e:
    if "is not registered under" in str(e):
        raise SystemExit(
            f"{e}; available: {sorted(type(plugin)._registry)}"
        ) from None
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14). Data as JSON: /api/errors/7973249136d4c43b. Report an issue: GitHub.