BoundaryML/baml · error · anyhow::Error

Invalid client property. Should have been a openai property

Error message

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

What it means

Same guard as the mod.rs resolver: the openai.rs resolve_properties expects the resolved client property to be the OpenAI variant, and bails with the actual property name if the destructuring `let ... else` fails. It indicates the OpenAI resolver received a property that resolved to a different provider type.

Source

Thrown at engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/openai.rs:18

use std::collections::HashMap;

use anyhow::{Context, Result};
use internal_llm_client::{openai::ResolvedOpenAI, ClientProvider, ResolvedClientProperty, UnresolvedClientProperty};

use crate::RuntimeContext;

use super::PostRequestProperties;

pub fn resolve_properties(
    provider: &ClientProvider,
    properties: &UnresolvedClientProperty<()>,
    ctx: &RuntimeContext,
) -> Result<ResolvedOpenAI> {
    let properties = properties.resolve(provider, &ctx.eval_ctx(false))?;

    let ResolvedClientProperty::OpenAI(props) = properties else {
        anyhow::bail!(
            "Invalid client property. Should have been a openai property but got: {}",
            properties.name()
        );
    };

    Ok(props)
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read the property name in the message and make the client's provider match an OpenAI provider in clients.baml.
  2. Regenerate/reload the BAML runtime client so property dispatch matches the current .baml files.
  3. If constructing clients in code, pass the OpenAI property to this resolver rather than another provider's.

Example fix

// before
client<C> { provider aws-bedrock options { ... } } // fed to openai resolver
// after
client<C> { provider openai options { model "gpt-4o-mini" api_key env.OPENAI_API_KEY } }
Defensive patterns

Strategy: type-guard

Validate before calling

// Dispatch by resolved variant rather than assuming OpenAI
match resolved_property {
    ResolvedClientProperty::OpenAI(p) => openai_path(p),
    other => return Err(anyhow!("expected OpenAI property, got {}", other.name())),
}

Type guard

let ResolvedClientProperty::OpenAI(props) = &resolved else {
    anyhow::bail!("not an OpenAI property: {}", resolved.name());
};

Prevention

When it happens

Trigger: Invoking the OpenAI-specific property resolution (properties/openai.rs) with an UnresolvedClientProperty that resolves to a non-OpenAI ResolvedClientProperty variant — e.g. an Azure, AWS, or retry-policy property passed by mistake.

Common situations: Hand-edited clients.baml where the provider string and the options block no longer correspond; runtime code that selects clients by name and hands the wrong property struct to the OpenAI path; stale generated code after changing a client's provider.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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