BoundaryML/baml · error

Invalid client property. Should have been a fallback propert

Error message

Invalid client property. Should have been a fallback property but got: {}

What it means

`FallbackStrategy::try_from` resolves a client's strategy properties and requires them to be of the `fallback` variant. If the resolved property is any other kind (e.g. round-robin or a plain client), this error is thrown naming the actual variant.

Source

Thrown at engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs:32

    runtime_interface::InternalClientLookup,
    RuntimeContext,
};

pub struct FallbackStrategy {
    pub name: String,
    pub(super) retry_policy: Option<String>,
    // TODO: We can add conditions to each client
    client_specs: Vec<ClientSpec>,
}

fn resolve_strategy(
    provider: &ClientProvider,
    properties: &UnresolvedClientProperty<()>,
    ctx: &RuntimeContext,
) -> Result<Vec<ClientSpec>> {
    let properties = properties.resolve(provider, &ctx.eval_ctx(false))?;
    let ResolvedClientProperty::Fallback(props) = properties else {
        anyhow::bail!(
            "Invalid client property. Should have been a fallback property but got: {}",
            properties.name()
        );
    };
    Ok(props.strategy)
}

impl TryFrom<(&ClientProperty, &RuntimeContext)> for FallbackStrategy {
    type Error = anyhow::Error;

    fn try_from(
        (client, ctx): (&ClientProperty, &RuntimeContext),
    ) -> std::result::Result<Self, Self::Error> {
        let strategy = resolve_strategy(&client.provider, &client.unresolved_options()?, ctx)?;
        Ok(Self {
            name: client.name.clone(),
            retry_policy: client.retry_policy.clone(),
            client_specs: strategy,

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Make the client's strategy property an actual `fallback` block with a `strategy` list of clients.
  2. If you intended round-robin, use the round-robin strategy client instead.
  3. Check spelling/structure of the strategy block in the .baml file and re-generate.
  4. Verify the client referenced via `client <name>` in a strategy is itself declared with the matching strategy properties.

Example fix

// before
client<MyLLMStrategy> Strategy {
  provider fallback
  strategy round_robin { ... }  // mismatch
}

// after
client<MyLLMStrategy> Strategy {
  provider fallback
  strategy {
    ClientA
    ClientB
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the strategy client before use
const resolved = clientProperties.resolve();
if (resolved.kind !== 'fallback') {
  throw new Error(`provider fallback requires a fallback strategy block, got ${resolved.kind}`);
}

Type guard

function isFallbackProperty(p) { return p && p.strategy === 'fallback' && Array.isArray(p.strategyClients); }

Try / catch

try { loadClient('MyStrategy'); } catch (e) { if (String(e).includes('Should have been a fallback property')) fixBamlStrategyBlock(); }

Prevention

When it happens

Trigger: Declaring a `strategy Fallback` (or a client referenced as fallback) whose properties resolve to a non-fallback shape — e.g. the BAML block defines a `strategy RoundRobin` but code paths construct a FallbackStrategy from it.

Common situations: Copy-pasting a client config where `strategy` keyword says fallback but the body/property type is round-robin (or vice versa), or pointing a strategy client at a non-strategy client property.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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