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
- Read the property name in the message and make the client's provider match an OpenAI provider in clients.baml.
- Regenerate/reload the BAML runtime client so property dispatch matches the current .baml files.
- 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
- Verify the client's provider string after any rename in .baml files.
- Run `baml-cli check` in CI to catch provider/property mismatches early.
- Avoid constructing UnresolvedClientProperty values by hand; use the BAML runtime's client lookup.
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
- Invalid client property. Should have been a openai property
- Either base_url or both (resource_name, deployment_id) must
- When using 'openai-generic', you must specify a base_url
- OpenAI transcription prompt is ambiguous: both properties.pr
- OpenAI transcriptions do not support reserved request field
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e738fcf45f360dd9.
Report an issue: GitHub.