{"record":{"id":"eff70f11b6a7286b","repo":"BoundaryML/baml","slug":"right-operand-of-must-be-bool-at","errorCode":null,"errorMessage":"right operand of && must be bool at {:?}","messagePattern":"right operand of && must be bool at (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-compiler/src/thir/interpret.rs","lineNumber":2478,"sourceCode":"            let greater = ord_opt\n                .map(|ord| matches!(ord, std::cmp::Ordering::Greater))\n                .ok_or_else(|| anyhow!(\"unsupported types for > operator at {:?}\", meta.0))?;\n            BamlValueWithMeta::Bool(greater, meta.clone())\n        }\n        BinaryOperator::GtEq => {\n            let ord_opt = compare_values(&left_val.clone(), &right_val.clone())?;\n            let greater_eq = ord_opt\n                .map(|ord| matches!(ord, std::cmp::Ordering::Greater | std::cmp::Ordering::Equal))\n                .ok_or_else(|| anyhow!(\"unsupported types for >= operator at {:?}\", meta.0))?;\n            BamlValueWithMeta::Bool(greater_eq, meta.clone())\n        }\n\n        // Logical operations\n        BinaryOperator::And => match left_val.clone() {\n            BamlValueWithMeta::Bool(false, _) => BamlValueWithMeta::Bool(false, meta.clone()),\n            BamlValueWithMeta::Bool(true, _) => match right_val.clone() {\n                BamlValueWithMeta::Bool(b, _) => BamlValueWithMeta::Bool(b, meta.clone()),\n                _ => bail!(\"right operand of && must be bool at {:?}\", meta.0),\n            },\n            _ => bail!(\"left operand of && must be bool at {:?}\", meta.0),\n        },\n        BinaryOperator::Or => match left_val.clone() {\n            BamlValueWithMeta::Bool(true, _) => BamlValueWithMeta::Bool(true, meta.clone()),\n            BamlValueWithMeta::Bool(false, _) => match right_val.clone() {\n                BamlValueWithMeta::Bool(b, _) => BamlValueWithMeta::Bool(b, meta.clone()),\n                _ => bail!(\"right operand of || must be bool at {:?}\", meta.0),\n            },\n            _ => bail!(\"left operand of || must be bool at {:?}\", meta.0),\n        },\n\n        // Bitwise operations (integer only)\n        BinaryOperator::BitAnd => match (left_val.clone(), right_val.clone()) {\n            (BamlValueWithMeta::Int(a, _), BamlValueWithMeta::Int(b, _)) => {\n                BamlValueWithMeta::Int(a & b, meta.clone())\n            }\n            _ => bail!(\"bitwise & requires integer operands at {:?}\", meta.0),","sourceCodeStart":2460,"sourceCodeEnd":2496,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-compiler/src/thir/interpret.rs#L2460-L2496","documentation":"The BAML compiler's interpreter short-circuits `&&`: when the left operand evaluates to `true`, the right operand must be a Bool for the result to be well-typed. This bail fires in evaluate_binary_op when the right operand of `&&` is any non-bool BamlValue (string, int, null, map, etc.). BAML's logical operators are strictly bool-typed and do not coerce truthy values.","triggerScenarios":"Evaluating a BAML expression like `a && b` where `a` is true and `b` is a non-boolean value (e.g. `true && 1`, `cond && \"yes\"`, `flag && maybeNull`). The error surfaces at interpretation time with the source span in meta.0.","commonSituations":"Porting JavaScript/Python-style truthy short-circuit idioms into BAML; using `x ?? default`-style fallbacks written as `flag && fallback`; a variable whose type was widened to nullable or string but still used in a boolean context.","solutions":["Make the right operand explicitly boolean, e.g. wrap it in a comparison: `flag && (x != null)`.","Check the right operand's declared type in the BAML schema; if it can be non-bool, restructure the expression with an if/else instead of `&&`.","If a value may be null, use an explicit null check before the `&&` rather than relying on truthiness."],"exampleFix":"// before (BAML)\nlet ok = hasData && items;\n// after\nlet ok = hasData && (items != null);","handlingStrategy":"type-guard","validationCode":"// before relying on &&, ensure both sides are bool\nfunction isBool(v) { return typeof v === 'boolean'; }\nif (!isBool(rightOperand)) throw new Error('right operand of && must be bool');","typeGuard":"const isBool = (v) => typeof v === 'boolean';","tryCatchPattern":"try {\n  result = evaluate(expr);\n} catch (e) {\n  if (String(e).includes('right operand of && must be bool')) {\n    // fix operand: coerce with explicit comparison\n    result = evaluate(fixBooleanOperands(expr));\n  } else throw e;\n}","preventionTips":["Never rely on truthiness in BAML; always write explicit comparisons","Keep a unit test per logical operator covering non-bool operands","Type-check expressions at compile time before interpretation"],"tags":["baml","type-mismatch","interpreter","logical-operator"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}