{"record":{"id":"e7aa6d9274244a33","repo":"langchain-ai/deepagents","slug":"str-exc-from-split-plugin-id-invalid-plugin-id","errorCode":null,"errorMessage":"{str(exc)} from split_plugin_id (invalid plugin id)","messagePattern":"(.+?) from split_plugin_id \\(invalid plugin id\\)","errorType":"exception","errorClass":"MarketplaceError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/plugins/discovery.py","lineNumber":186,"sourceCode":"\n\n@plugin_mutation_lock()\ndef uninstall_plugin(plugin_id: str) -> None:\n    \"\"\"Uninstall a plugin (disable, clear records, delete orphaned cache).\n\n    Args:\n        plugin_id: Plugin id in `{name}@{marketplace}` form.\n    \"\"\"\n    uninstall_plugin_record(plugin_id)\n\n\ndef _resolve_marketplace_and_entry(\n    plugin_id: str,\n) -> tuple[PluginMarketplace, MarketplacePluginEntry]:\n    try:\n        plugin_name, marketplace_name = split_plugin_id(plugin_id)\n    except ValueError as exc:\n        raise MarketplaceError(str(exc)) from exc\n    records = load_marketplace_records()\n    record = records.get(marketplace_name)\n    if record is None:\n        msg = f\"Marketplace {marketplace_name!r} is not configured\"\n        raise MarketplaceError(msg)\n    marketplace = load_marketplace_location(Path(record.install_location))\n    entry = next(\n        (plugin for plugin in marketplace.plugins if plugin.name == plugin_name),\n        None,\n    )\n    if entry is None:\n        msg = f\"Plugin {plugin_id!r} not found in marketplace {marketplace_name}\"\n        raise MarketplaceError(msg)\n    return marketplace, entry\n\n\n@plugin_mutation_lock()\ndef install_plugin(plugin_id: str) -> PluginInstance:","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/plugins/discovery.py#L168-L204","documentation":"_resolve_marketplace_and_entry splits the plugin id into plugin and marketplace names; when split_plugin_id raises ValueError (malformed id), the ValueError is re-raised as a MarketplaceError with the original message plus the hint 'from split_plugin_id (invalid plugin id)'. It signals the plugin id string does not have the expected `name@marketplace` shape.","triggerScenarios":"Calling install_plugin (or the CLI `plugin install`) with an id lacking the `@` separator, containing multiple/empty segments, or otherwise rejected by split_plugin_id.","commonSituations":"Typing just the plugin name (`widget`) instead of `widget@internal`; copy-pasting an id that lost its `@marketplace` tail; shell quoting/escaping stripping characters from the id.","solutions":["Use the full `plugin@marketplace` form, e.g. `plugin install widget@internal`.","Check for shell quoting issues that mangle the `@`.","Read the embedded split_plugin_id message — it states exactly what was wrong with the id.","Run `plugin marketplace list` to get correct marketplace names."],"exampleFix":"// before\ndcode plugin install widget\n# MarketplaceError: ... from split_plugin_id (invalid plugin id)\n// after\ndcode plugin install widget@internal","handlingStrategy":"validation","validationCode":"def ensure_plugin_id_shape(plugin_id: str) -> str:\n    name, sep, market = plugin_id.partition(\"@\")\n    if not sep or not name or not market:\n        raise SystemExit(f\"invalid plugin id {plugin_id!r}; expected 'name@marketplace'\")\n    return plugin_id","typeGuard":"def is_valid_plugin_id(plugin_id: str) -> bool:\n    name, sep, market = plugin_id.partition(\"@\")\n    return bool(sep and name and market and \"@\" not in market)","tryCatchPattern":"from deepagents_code.plugins.discovery import MarketplaceError, install_plugin\n\ntry:\n    install_plugin(\"widget@internal\")\nexcept MarketplaceError as exc:\n    if \"split_plugin_id\" in str(exc):\n        print(\"fix the plugin id format: name@marketplace\")\n    else:\n        raise","preventionTips":["Always write ids as `name@marketplace`.","Quote ids in shells so '@' and segments are not mangled.","Copy ids verbatim from marketplace listings.","Split on the first '@' only when parsing manually.","Add a pre-install id-format check in scripts."],"tags":["plugin-id","argument-validation"],"backgroundTag":"invalid-plugin-id","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}