{"record":{"id":"ddaa3f4a58e2238a","repo":"HKUDS/Vibe-Trading","slug":"unknown-zoo-v-r-expected-one-of-sorted-valid","errorCode":null,"errorMessage":"unknown zoo {v!r}; expected one of {sorted(_VALID_ZOOS)}","messagePattern":"unknown zoo (.+?); expected one of (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"agent/src/api/alpha_routes.py","lineNumber":164,"sourceCode":"\n# ---------------------------------------------------------------------------\n# Request/response schemas\n# ---------------------------------------------------------------------------\n\n\nclass BenchRequest(BaseModel):\n    \"\"\"POST /alpha/bench body.\"\"\"\n\n    zoo: str = Field(..., min_length=1, max_length=64)\n    universe: str = Field(..., min_length=1, max_length=64)\n    period: str = Field(..., min_length=4, max_length=32)\n    top: int = Field(20, ge=1, le=500)\n\n    @field_validator(\"zoo\")\n    @classmethod\n    def _zoo_known(cls, v: str) -> str:\n        if v not in _VALID_ZOOS:\n            raise ValueError(\n                f\"unknown zoo {v!r}; expected one of {sorted(_VALID_ZOOS)}\"\n            )\n        return v\n\n    @field_validator(\"universe\")\n    @classmethod\n    def _universe_known(cls, v: str) -> str:\n        if v not in _BENCH_UNIVERSES:\n            raise ValueError(\n                f\"unknown universe {v!r}; expected one of {sorted(_BENCH_UNIVERSES)}\"\n            )\n        return v\n\n\nclass CompareRequest(BaseModel):\n    \"\"\"POST /alpha/compare body — a head-to-head of >= 2 named alphas.\"\"\"\n\n    alpha_ids: list[str] = Field(..., min_length=2, max_length=50)","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/api/alpha_routes.py#L146-L182","documentation":"load_adapter dynamically imports a user-installed local connector adapter module via importlib.util.spec_from_file_location. If the spec or its loader cannot be created — typically because plugin.module_path points to a file that no longer exists or is unreadable — a bare RuntimeError is raised with the profile id. It means the plugin manifest is registered but its module file can't be located/loaded.","triggerScenarios":"Calling any read operation (check_connection, get_account, get_positions, etc.) through _local_plugin_call for a profile whose local plugin file was deleted, moved, or has wrong permissions after installation; a stale plugin registry entry whose module_path no longer resolves.","commonSituations":"User manually deleted or moved the connector directory under the plugin root, synced/cleaned the workspace, or the plugin was installed from a different machine/user with absolute paths that no longer hold.","solutions":["Verify the plugin's module_path file exists on disk (inspect the plugin registry/manifest) and restore or reinstall it","Reinstall the connector with the install command, or uninstall the stale plugin entry so discovery stops returning it","If the path is valid, check file permissions and that the path is a regular .py file"],"exampleFix":"# before: stale registry entry, file moved\nplugin = plugin_by_profile_id(profile.id)\nadapter = load_adapter(plugin)  # RuntimeError\n\n# after: validate path before loading\nfrom pathlib import Path\nif not Path(plugin.module_path).is_file():\n    raise FileNotFoundError(f\"plugin module missing: {plugin.module_path}\")\nadapter = load_adapter(plugin)","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef plugin_module_loadable(plugin) -> bool:\n    p = Path(plugin.module_path)\n    return p.is_file() and p.suffix == \".py\" and os.access(p, os.R_OK)","typeGuard":null,"tryCatchPattern":"try:\n    adapter = load_adapter(plugin)\nexcept RuntimeError as e:\n    if \"cannot load connector adapter\" in str(e):\n        uninstall_or_repair_plugin(plugin)  # restore module_path or drop entry\n    raise","preventionTips":["Reinstall connectors through install_connector rather than copying files manually","Validate plugin.module_path exists before invoking read operations","Periodically prune registry entries whose module files are gone"],"tags":["plugin-system","import","local-connector","trading"],"backgroundTag":"module-not-found","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}