hiyouga/LlamaFactory · error · TypeError

kernel_config.name must be a string.

Error message

kernel_config.name must be a string.

What it means

apply_kernels() expects kernel_config['name'] to be a comma-separated string of kernel names. Any other type (list, None, dict) raises TypeError immediately — this is an API-contract check on the config schema.

Source

Thrown at src/llamafactory/v1/plugins/model_plugins/kernels/interface.py:48

_AUTO_KERNELS = {
    DeviceType.NPU: ("npu_fused_moe", "npu_fused_rmsnorm", "npu_fused_rope", "npu_fused_swiglu"),
}


def _apply_auto_kernels(model: HFModel, **kwargs) -> HFModel:
    device_type = get_current_accelerator().type
    for kernel_name in _AUTO_KERNELS.get(device_type, ()):
        model = KernelPlugin(kernel_name).apply(model=model, **kwargs)

    return model


def apply_kernels(model: HFModel, config: dict[str, Any], require_logits: bool = False) -> HFModel:
    """Apply the comma-separated kernel names selected by ``kernel_config.name``."""
    kernel_names = config.get("name")
    if not isinstance(kernel_names, str):
        raise TypeError("kernel_config.name must be a string.")

    names = [name.strip() for name in kernel_names.split(",") if name.strip()]
    if not names:
        raise ValueError("kernel_config.name must contain at least one kernel name.")

    for name in names:
        if name == "auto":
            model = _apply_auto_kernels(model=model, config=config, require_logits=require_logits)
        else:
            model = KernelPlugin(name).apply(model=model, config=config, require_logits=require_logits)

    return model


def apply_v1_kernels(model: HFModel, use_v1_kernels: bool) -> HFModel:
    """Apply v1 automatic kernels for the transitional v0 ``use_v1_kernels`` option."""
    if not use_v1_kernels:
        return model

View on GitHub (pinned to f28afaf635)

Solutions

  1. Use a single comma-separated string: name: "liger_kernel,flash-linear-attention".
  2. For programmatic configs, ",".join(names) before calling.
  3. Omit the key entirely if the caller treats missing config as no kernels, rather than passing None.

Example fix

# before
kernel_config = {"name": ["liger_kernel"]}

# after
kernel_config = {"name": "liger_kernel"}
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(kernel_config.get('name'), str), 'kernel_config.name must be a comma-separated string'

Type guard

def is_kernel_name_str(cfg: dict) -> bool:
    """True when cfg['name'] is a str (possibly comma-separated)."""
    return isinstance(cfg.get('name'), str)

Try / catch

try:
    apply_kernels(model, cfg)
except TypeError as e:
    if 'must be a string' in str(e):
        cfg['name'] = ','.join(cfg['name']) if isinstance(cfg['name'], list) else cfg['name']
        apply_kernels(model, cfg)
    else:
        raise

Prevention

When it happens

Trigger: Passing kernel_config as {"name": ["liger_kernel", "fla"]} (list) or {"name": None} to apply_kernels; YAML where name parses as a list.

Common situations: Users naturally write a YAML list for multiple kernels; programmatic configs built with lists; copy-pasting a v0-style structure with different keys.

Related errors


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