{"record":{"id":"bb72f74789e793cd","repo":"hiyouga/LlamaFactory","slug":"multimodal-plugin-name-already-exists","errorCode":null,"errorMessage":"Multimodal plugin {name} already exists.","messagePattern":"Multimodal plugin (.+?) already exists\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/data/mm_plugin.py","lineNumber":3277,"sourceCode":"    \"minicpm_v\": MiniCPMVPlugin,\n    \"minicpm_v_4_6\": MiniCPMV4_6Plugin,\n    \"mllama\": MllamaPlugin,\n    \"moss_vl\": MossVLPlugin,\n    \"paligemma\": PaliGemmaPlugin,\n    \"pixtral\": PixtralPlugin,\n    \"qwen2_audio\": Qwen2AudioPlugin,\n    \"qwen2_omni\": Qwen2OmniPlugin,\n    \"qwen2_vl\": Qwen2VLPlugin,\n    \"qwen3_vl\": Qwen3VLPlugin,\n    \"video_llava\": VideoLlavaPlugin,\n    \"youtu_vl\": YoutuVLPlugin,\n}\n\n\ndef register_mm_plugin(name: str, plugin_class: type[\"BasePlugin\"]) -> None:\n    r\"\"\"Register a multimodal plugin.\"\"\"\n    if name in PLUGINS:\n        raise ValueError(f\"Multimodal plugin {name} already exists.\")\n\n    PLUGINS[name] = plugin_class\n\n\ndef get_mm_plugin(\n    name: str,\n    image_token: str | None = None,\n    video_token: str | None = None,\n    audio_token: str | None = None,\n    **kwargs,\n) -> \"BasePlugin\":\n    r\"\"\"Get plugin for multimodal inputs.\"\"\"\n    if name not in PLUGINS:\n        raise ValueError(f\"Multimodal plugin `{name}` not found.\")\n\n    return PLUGINS[name](image_token, video_token, audio_token, **kwargs)\n","sourceCodeStart":3259,"sourceCodeEnd":3294,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/data/mm_plugin.py#L3259-L3294","documentation":"register_mm_plugin raises when the plugin name is already a key in the global PLUGINS dict. The registry (qwen2_vl, qwen2_omni, minicpm_v, moss_vl, ...) is populated at import; registering under an existing name would silently replace the built-in plugin, so it is refused.","triggerScenarios":"Calling register_mm_plugin('qwen2_vl', MyPlugin) — any built-in name collides. Also double registration if a custom registration module is imported twice (e.g. re-imported under a different path).","commonSituations":"Users adding a custom plugin and forgetting to pick a unique name; module-level registration executed twice due to importlib.reload or duplicated module copies.","solutions":["Choose a unique, namespaced plugin name (e.g. 'myorg_custom_vl').","Guard double registration: `if name not in PLUGINS: register_mm_plugin(name, cls)`.","Check the PLUGINS dict keys before registering to confirm the collision."],"exampleFix":"# before\nregister_mm_plugin('qwen2_vl', MyPlugin)  # collides\n# after\nregister_mm_plugin('my_org_vl', MyPlugin)\nplugin = get_mm_plugin(name='my_org_vl', ...)","handlingStrategy":"type-guard","validationCode":"from llamafactory.data.mm_plugin import PLUGINS\n\nNAME = 'my_org_vl'\nif NAME not in PLUGINS:\n    register_mm_plugin(NAME, MyPlugin)","typeGuard":"def plugin_name_free(name: str) -> bool:\n    from llamafactory.data.mm_plugin import PLUGINS\n    return name not in PLUGINS","tryCatchPattern":"try:\n    register_mm_plugin(name, cls)\nexcept ValueError:\n    if PLUGINS.get(name) is not cls:\n        raise  # real collision with someone else's plugin","preventionTips":["Prefix custom plugin names with an org/project namespace.","Register plugins once at application startup, not per-import in library modules."],"tags":["plugin-registry","multimodal","extension-api","name-collision"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}