{"record":{"id":"68f01ebf6d94fd77","repo":"BoundaryML/baml","slug":"invalid-client-property-should-have-been-a-fallback-property","errorCode":null,"errorMessage":"Invalid client property. Should have been a fallback property but got: {}","messagePattern":"Invalid client property\\. Should have been a fallback property but got: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs","lineNumber":32,"sourceCode":"    runtime_interface::InternalClientLookup,\n    RuntimeContext,\n};\n\npub struct FallbackStrategy {\n    pub name: String,\n    pub(super) retry_policy: Option<String>,\n    // TODO: We can add conditions to each client\n    client_specs: Vec<ClientSpec>,\n}\n\nfn resolve_strategy(\n    provider: &ClientProvider,\n    properties: &UnresolvedClientProperty<()>,\n    ctx: &RuntimeContext,\n) -> Result<Vec<ClientSpec>> {\n    let properties = properties.resolve(provider, &ctx.eval_ctx(false))?;\n    let ResolvedClientProperty::Fallback(props) = properties else {\n        anyhow::bail!(\n            \"Invalid client property. Should have been a fallback property but got: {}\",\n            properties.name()\n        );\n    };\n    Ok(props.strategy)\n}\n\nimpl TryFrom<(&ClientProperty, &RuntimeContext)> for FallbackStrategy {\n    type Error = anyhow::Error;\n\n    fn try_from(\n        (client, ctx): (&ClientProperty, &RuntimeContext),\n    ) -> std::result::Result<Self, Self::Error> {\n        let strategy = resolve_strategy(&client.provider, &client.unresolved_options()?, ctx)?;\n        Ok(Self {\n            name: client.name.clone(),\n            retry_policy: client.retry_policy.clone(),\n            client_specs: strategy,","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs#L14-L50","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the client's strategy property an actual `fallback` block with a `strategy` list of clients.","If you intended round-robin, use the round-robin strategy client instead.","Check spelling/structure of the strategy block in the .baml file and re-generate.","Verify the client referenced via `client <name>` in a strategy is itself declared with the matching strategy properties."],"exampleFix":"// before\nclient<MyLLMStrategy> Strategy {\n  provider fallback\n  strategy round_robin { ... }  // mismatch\n}\n\n// after\nclient<MyLLMStrategy> Strategy {\n  provider fallback\n  strategy {\n    ClientA\n    ClientB\n  }\n}","handlingStrategy":"validation","validationCode":"// Validate the strategy client before use\nconst resolved = clientProperties.resolve();\nif (resolved.kind !== 'fallback') {\n  throw new Error(`provider fallback requires a fallback strategy block, got ${resolved.kind}`);\n}","typeGuard":"function isFallbackProperty(p) { return p && p.strategy === 'fallback' && Array.isArray(p.strategyClients); }","tryCatchPattern":"try { loadClient('MyStrategy'); } catch (e) { if (String(e).includes('Should have been a fallback property')) fixBamlStrategyBlock(); }","preventionTips":["Match strategy blocks exactly to the provider keyword (fallback ↔ fallback shape)","Run `baml-cli generate`/`baml-cli dev` to validate config before runtime","Avoid copy-pasting between fallback and round-robin blocks without renaming"],"tags":["configuration","baml","strategy","fallback"],"backgroundTag":"invalid-config-value","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}