BoundaryML/baml · error

Strategy provider is empty: {}

Error message

Strategy provider is empty: {}

What it means

In llm_provider's chat_to_message, for a strategy-style provider the orchestrator resolves the strategy to a list of candidate clients, and .first() must yield one. If the orchestrator returns an empty list for the provider name, this error fires: the named strategy resolved to zero providers, so there is nothing to send the chat to.

Source

Thrown at engine/baml-runtime/src/internal/llm_client/llm_provider.rs:87

        chat: &[RenderedChatMessage],
        ctx: &RuntimeContext,
        client_lookup: &'a dyn InternalClientLookup<'a>,
    ) -> Result<serde_json::Map<String, serde_json::Value>> {
        match self {
            LLMProvider::Primitive(provider) => provider.chat_to_message(chat),

            // Return the first node's provider implementation.
            LLMProvider::Strategy(provider) => {
                let orchestrator = provider.iter_orchestrator(
                    &mut Default::default(),
                    Default::default(),
                    ctx,
                    client_lookup,
                )?;

                orchestrator
                    .first()
                    .ok_or(anyhow::anyhow!("Strategy provider is empty: {}", provider))?
                    .provider
                    .chat_to_message(chat)
            }
        }
    }

    pub fn completion_to_provider_body<'a>(
        &self,
        prompt: &str,
        ctx: &RuntimeContext,
        client_lookup: &'a dyn InternalClientLookup<'a>,
    ) -> Result<serde_json::Map<String, serde_json::Value>> {
        match self {
            LLMProvider::Primitive(provider) => provider.completion_to_provider_body(prompt),

            LLMProvider::Strategy(provider) => {
                let orchestrator = provider.iter_orchestrator(
                    &mut Default::default(),

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Ensure the strategy in baml.config declares at least one client in its clients array.
  2. Verify every client referenced by the strategy exists and is spelled correctly.
  3. Check the strategy name passed as provider matches the strategy defined in configuration.
  4. Add a default/primary client instead of an empty strategy so requests always have a target.

Example fix

// before (baml)
client Strategy {
  provider retry
  strategy {
    // clients list is empty
  }
}
// after (baml)
client Strategy {
  provider retry
  strategy {
    ClientA
    ClientB
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Before using a strategy provider, verify it resolves to at least one client.
fn validate_strategy(config: &RuntimeConfig, strategy_name: &str) -> Result<(), String> {
    let strategy = config.llm_clients.iter().find(|c| c.name == strategy_name)
        .ok_or_else(|| format!("strategy `{}` not defined", strategy_name))?;
    if strategy.clients.is_empty() {
        return Err(format!("strategy `{}` has no clients", strategy_name));
    }
    for c in &strategy.clients {
        if !config.llm_clients.iter().any(|k| &k.name == c) {
            return Err(format!("strategy `{}` references unknown client `{}`", strategy_name, c));
        }
    }
    Ok(())
}

Type guard

fn strategy_has_clients(cfg: &RuntimeConfig, name: &str) -> bool {
    cfg.llm_clients.iter()
        .find(|c| c.name == name)
        .map_or(false, |c| !c.clients.is_empty())
}

Try / catch

match provider.chat_to_message(chat) {
    Ok(m) => m,
    Err(e) if e.to_string().starts_with("Strategy provider is empty") => {
        eprintln!("Fix the strategy's clients list in baml.config");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling chat_to_message on a provider whose name refers to a strategy (retry/fallback strategy) but whose strategy configuration produces an empty client list — e.g. the strategy's clients array is empty or all referenced clients failed to resolve.

Common situations: A baml.config strategy block referencing clients by name that are not defined or were filtered out; an empty clients list under a strategy; typo'd strategy name causing resolution to silently produce no entries.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/249ce63373134004. Report an issue: GitHub.