virattt/ai-hedge-fund · error · ValueError

No v2 client for {provider} (model {model}). Supported: {',

Error message

No v2 client for {provider} (model {model}). Supported: {', '.join(sorted(SUPPORTED_PROVIDERS))}.

What it means

Raised by make_llm (hedge_fund/llm/client.py:105) when the resolved provider has no v2 chat client implementation. The provider comes from provider_for(model) — unlisted model ids default to Anthropic — and is checked against SUPPORTED_PROVIDERS (Anthropic, OpenAI, xAI, DeepSeek, Google, Kimi). Since the supported set currently equals the whole registry, hitting this means provider_for returned something unexpected (or the registry grew without a transport).

Source

Thrown at hedge_fund/llm/client.py:105

    model: str | None = None,
    timeout: float = 60.0,
    max_tokens: int = 4096,
    on_token: TokenListener = None,
) -> ChatLLM:
    """Build the client for a model id, routed by the registry's provider.

    The id comes from the caller, else HEDGE_FUND_LLM_MODEL, else DEFAULT_MODEL — the
    same seam the TUI's picker writes to. Raises with the name of the missing
    environment variable, because that is the only thing the user can act on.
    """
    model = model or os.environ.get("HEDGE_FUND_LLM_MODEL") or DEFAULT_MODEL
    provider = provider_for(model)
    if provider is None:
        # Unlisted ids still work: a model newer than the registry should not
        # need a code change. Anthropic is the default transport.
        provider = "Anthropic"
    if not is_supported(provider):
        raise ValueError(
            f"No v2 client for {provider} (model {model}). "
            f"Supported: {', '.join(sorted(SUPPORTED_PROVIDERS))}."
        )

    api_key = _require_key(provider)

    if provider == "Anthropic":
        from langchain_anthropic import ChatAnthropic
        chat = ChatAnthropic(model=model, api_key=api_key, timeout=timeout,
                             max_retries=1, max_tokens=max_tokens)
    elif provider == "OpenAI":
        from langchain_openai import ChatOpenAI
        chat = ChatOpenAI(model=model, api_key=api_key, timeout=timeout,
                          max_retries=1, base_url=os.getenv("OPENAI_API_BASE"))
    elif provider == "DeepSeek":
        from langchain_deepseek import ChatDeepSeek
        chat = ChatDeepSeek(model=model, api_key=api_key, timeout=timeout,
                            max_retries=1)

View on GitHub (pinned to eff8a7320f)

Solutions

  1. Set HEDGE_FUND_LLM_MODEL to a known model (default 'claude-sonnet-5') or pass model= explicitly with a supported id from the registry.
  2. If you need the unsupported provider, add the langchain transport branch for it in make_llm and ensure it's in PROVIDER_ENV_VARS/SUPPORTED_PROVIDERS — then the check passes.
  3. Inspect provider_for(model) for your exact id to see which provider it resolves to; the error names both provider and model.

Example fix

# before
os.environ["HEDGE_FUND_LLM_MODEL"] = "mistral-large"
chat = make_llm()  # ValueError: No v2 client for ...

# after
os.environ["HEDGE_FUND_LLM_MODEL"] = "claude-sonnet-5"
chat = make_llm()
Defensive patterns

Strategy: validation

Validate before calling

from hedge_fund.llm.registry import SUPPORTED_PROVIDERS, provider_for

def model_is_runnable(model_id: str) -> bool:
    provider = provider_for(model_id) or "Anthropic"  # same default as make_llm
    return provider in SUPPORTED_PROVIDERS

Type guard

from hedge_fund.llm.registry import SUPPORTED_PROVIDERS, provider_for

def resolves_to_supported_provider(model_id: str) -> bool:
    p = provider_for(model_id)
    return (p or "Anthropic") in SUPPORTED_PROVIDERS

Try / catch

try:
    chat = make_llm(model=model_id)
except ValueError as e:
    if "No v2 client" in str(e):
        raise SystemExit(
            f"model {model_id!r} has no transport; pick one of the registry models"
        ) from e
    raise

Prevention

When it happens

Trigger: Setting HEDGE_FUND_LLM_MODEL (or passing model=) to an id that provider_for maps to a provider not in {Anthropic, OpenAI, xAI, DeepSeek, Google, Kimi}; a custom/extended registry entry added without a corresponding client branch in make_llm; a TUI picker selection of a provider row that is shown but not backed by a transport (the registry comment notes such rows should be non-selectable).

Common situations: New model id added to the registry file before the transport existed; HEDGE_FUND_LLM_MODEL left over from a fork that supported a provider (e.g. 'Mistral') this build doesn't; env var pointing at a typo'd model string that maps oddly.

Related errors


AI-assisted analysis of virattt/ai-hedge-fund@eff8a7320f (2026-08-15). Data as JSON: /api/errors/d10bb570745465aa. Report an issue: GitHub.