BoundaryML/baml · error

Invalid client property. Should have been a anthropic…

Error message

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

What it means

resolve_properties expects the resolved client property block to be an Anthropic-specific property type; when the resolved variant is anything else, BAML bails with this type error naming what it got instead. It is an internal configuration-shape mismatch between the provider and the parsed client property.

Solutions

  1. Check that provider is exactly "anthropic" and the options block matches Anthropic's schema (api_key, model, etc.)
  2. Remove foreign options fields copied from other providers
  3. Ensure dynamic property injection returns an Anthropic-shaped property object
  4. Pin/align the BAML runtime/CLI versions so the anthropic property parser matches

Example fix

// before (baml)
client "claude" {
  provider anthropic
  options { api_key env.OPENAI_API_KEY base_url "https://api.openai.com" } // openai-shaped options
}
// after
client "claude" {
  provider anthropic
  options { api_key env.ANTHROPIC_API_KEY model "claude-3-5-sonnet-latest" }
}
Defensive patterns

Strategy: validation

Validate before calling

// baml-src check or runtime config validation
function validateAnthropicClient(cfg) {
  if (cfg.provider !== 'anthropic') throw new Error('provider must be anthropic');
  for (const k of Object.keys(cfg.options)) {
    if (!['api_key','model','base_url','max_tokens','temperature'].includes(k))
      throw new Error(`unknown anthropic option: ${k}`);
  }
}

Type guard

const isAnthropicProps = (p) => p && typeof p === 'object' && p.type === 'anthropic_properties';

Try / catch

try {
  return await b.functions.F(x);
} catch (e) {
  if (/Invalid client property/.test(String(e))) {
    throw new Error('Fix clients.baml: anthropic provider needs anthropic-shaped options');
  }
  throw e;
}

Prevention

When it happens

Trigger: Declaring a client with provider "anthropic" whose options/properties resolve to a non-Anthropic ResolvedClientProperty variant — e.g. misconfigured properties block, wrong provider string, or custom properties that resolve to a generic variant.

Common situations: Copy-pasted client config from another provider (openai/aws) with provider renamed to anthropic but options shape unchanged; plugin/dynamic property resolution returning the wrong variant; version mismatch where anthropic options schema changed.

Related errors


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

Appendix: source

Thrown at engine/baml-runtime/src/internal/llm_client/primitive/anthropic/anthropic_client.rs:60

    context: RenderContext_Client,
    features: ModelFeatures,
    properties: ResolvedAnthropic,

    // clients
    client: reqwest::Client,
}

// resolves/constructs PostRequestProperties from the client's options and runtime context, fleshing out the needed headers and parameters
// basically just reads the client's options and matches them to needed properties or defaults them
fn resolve_properties(
    provider: &ClientProvider,
    properties: &UnresolvedClientProperty<()>,
    ctx: &RuntimeContext,
) -> Result<ResolvedAnthropic, anyhow::Error> {
    let properties = properties.resolve(provider, &ctx.eval_ctx(false))?;

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

    Ok(props)
}
// getters for client info
impl WithRetryPolicy for AnthropicClient {
    fn retry_policy_name(&self) -> Option<&str> {
        self.retry_policy.as_deref()
    }
}

impl WithClientProperties for AnthropicClient {
    fn allowed_metadata(&self) -> &AllowedRoleMetadata {
        &self.properties.allowed_metadata
    }

View on GitHub (pinned to bd85ce9dee)