HKUDS/Vibe-Trading · error · HTTPException

unknown zoo {zoo!r}; expected one of {sorted(_VALID_ZOOS)}

Error message

unknown zoo {zoo!r}; expected one of {sorted(_VALID_ZOOS)}

What it means

install_connector validates the connector directory, then copies it into the shared plugin root under the connector name. If root/<connector> already exists it raises ValueError, enforcing one installed copy per connector id.

Source

Thrown at agent/src/api/alpha_routes.py:392

        if require_auth is None:
            require_auth = host.require_auth
        if require_event_stream_auth is None:
            require_event_stream_auth = host.require_event_stream_auth

    # -----------------------------------------------------------------------
    # GET /alpha/list
    # -----------------------------------------------------------------------

    @app.get("/alpha/list", dependencies=[Depends(require_auth)])
    async def list_alphas(
        zoo: str | None = Query(None, max_length=64),
        theme: str | None = Query(None, max_length=64),
        universe: str | None = Query(None, max_length=64),
        limit: int = Query(100, ge=1, le=1000),
    ) -> dict[str, Any]:
        """List alphas, optionally filtered by zoo / theme / universe."""
        if zoo is not None and zoo not in _VALID_ZOOS:
            raise HTTPException(
                status_code=400,
                detail=f"unknown zoo {zoo!r}; expected one of {sorted(_VALID_ZOOS)}",
            )
        if theme is not None and theme not in _VALID_THEMES:
            raise HTTPException(
                status_code=400,
                detail=f"unknown theme {theme!r}; expected one of {sorted(_VALID_THEMES)}",
            )
        if universe is not None:
            _ALIAS = {"csi300": "equity_cn", "sp500": "equity_us", "btc-usdt": "crypto"}
            universe = _ALIAS.get(universe, universe)
        if universe is not None and universe not in _VALID_UNIVERSES:
            raise HTTPException(
                status_code=400,
                detail=f"unknown universe {universe!r}; expected one of {sorted(_VALID_UNIVERSES)}",
            )

        from src.factors.registry import get_default_registry

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Uninstall/remove the existing directory under plugin_root()/<connector> first, then reinstall
  2. Or overwrite manually: remove the target dir and re-run install so the edited source is copied in
  3. Guard install scripts with an existence check before calling install_connector

Example fix

# before
install_connector(Path("./acme-broker"))  # ValueError: already installed

# after
from src.trading.plugin_scaffold import install_connector, plugin_root
import shutil
target = plugin_root() / "acme-broker"
if target.exists():
    shutil.rmtree(target)
install_connector(Path("./acme-broker"))
Defensive patterns

Strategy: validation

Validate before calling

from src.trading.plugin_scaffold import plugin_root
from src.trading.local_plugins import validate_connector

def install_is_clean(directory) -> bool:
    plugin = validate_connector(directory)
    return not (plugin_root() / plugin.profile.connector).exists()

Try / catch

try:
    install_connector(directory)
except ValueError as e:
    if "already installed" in str(e):
        target = plugin_root() / validate_connector(directory).profile.connector
        shutil.rmtree(target)
        install_connector(directory)  # refresh install
    else:
        raise

Prevention

When it happens

Trigger: Running connector install twice without uninstalling; installing a second variant of the same connector id from a different source directory.

Common situations: Re-running an install script after editing the connector source — developers expect overwrite but get an error; CI pipelines installing repeatedly into a persistent plugin root.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/fa6d1bb76dacb6f8. Report an issue: GitHub.