{"record":{"id":"68463b6f7b37da8d","repo":"hiyouga/LlamaFactory","slug":"kernel-config-name-must-be-a-string","errorCode":null,"errorMessage":"kernel_config.name must be a string.","messagePattern":"kernel_config\\.name must be a string\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/plugins/model_plugins/kernels/interface.py","lineNumber":48,"sourceCode":"\n_AUTO_KERNELS = {\n    DeviceType.NPU: (\"npu_fused_moe\", \"npu_fused_rmsnorm\", \"npu_fused_rope\", \"npu_fused_swiglu\"),\n}\n\n\ndef _apply_auto_kernels(model: HFModel, **kwargs) -> HFModel:\n    device_type = get_current_accelerator().type\n    for kernel_name in _AUTO_KERNELS.get(device_type, ()):\n        model = KernelPlugin(kernel_name).apply(model=model, **kwargs)\n\n    return model\n\n\ndef apply_kernels(model: HFModel, config: dict[str, Any], require_logits: bool = False) -> HFModel:\n    \"\"\"Apply the comma-separated kernel names selected by ``kernel_config.name``.\"\"\"\n    kernel_names = config.get(\"name\")\n    if not isinstance(kernel_names, str):\n        raise TypeError(\"kernel_config.name must be a string.\")\n\n    names = [name.strip() for name in kernel_names.split(\",\") if name.strip()]\n    if not names:\n        raise ValueError(\"kernel_config.name must contain at least one kernel name.\")\n\n    for name in names:\n        if name == \"auto\":\n            model = _apply_auto_kernels(model=model, config=config, require_logits=require_logits)\n        else:\n            model = KernelPlugin(name).apply(model=model, config=config, require_logits=require_logits)\n\n    return model\n\n\ndef apply_v1_kernels(model: HFModel, use_v1_kernels: bool) -> HFModel:\n    \"\"\"Apply v1 automatic kernels for the transitional v0 ``use_v1_kernels`` option.\"\"\"\n    if not use_v1_kernels:\n        return model","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/plugins/model_plugins/kernels/interface.py#L30-L66","documentation":"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.","triggerScenarios":"Passing kernel_config as {\"name\": [\"liger_kernel\", \"fla\"]} (list) or {\"name\": None} to apply_kernels; YAML where name parses as a list.","commonSituations":"Users naturally write a YAML list for multiple kernels; programmatic configs built with lists; copy-pasting a v0-style structure with different keys.","solutions":["Use a single comma-separated string: name: \"liger_kernel,flash-linear-attention\".","For programmatic configs, \",\".join(names) before calling.","Omit the key entirely if the caller treats missing config as no kernels, rather than passing None."],"exampleFix":"# before\nkernel_config = {\"name\": [\"liger_kernel\"]}\n\n# after\nkernel_config = {\"name\": \"liger_kernel\"}","handlingStrategy":"type-guard","validationCode":"assert isinstance(kernel_config.get('name'), str), 'kernel_config.name must be a comma-separated string'","typeGuard":"def is_kernel_name_str(cfg: dict) -> bool:\n    \"\"\"True when cfg['name'] is a str (possibly comma-separated).\"\"\"\n    return isinstance(cfg.get('name'), str)","tryCatchPattern":"try:\n    apply_kernels(model, cfg)\nexcept TypeError as e:\n    if 'must be a string' in str(e):\n        cfg['name'] = ','.join(cfg['name']) if isinstance(cfg['name'], list) else cfg['name']\n        apply_kernels(model, cfg)\n    else:\n        raise","preventionTips":["Normalize lists to comma-joined strings at the config boundary.","Schema-validate kernel_config (name: str) before training.","Follow the documented YAML shape exactly."],"tags":["kernels","config","type-error","validation"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}