BoundaryML/baml · error

left operand of || must be bool at

Error message

left operand of || must be bool at {:?}

What it means

The `||` operator in BAML's interpreter requires both operands to be Bool. If the left operand is not BamlValueWithMeta::Bool (it didn't short-circuit as true), evaluate_binary_op bails with this message. No truthiness coercion is performed.

Solutions

  1. Add an explicit comparison to make the left operand bool: `(configValue != null) || defaultFlag`.
  2. Inspect the left operand's type; if it comes from LLM output or config, coerce with an explicit equality or null check first.
  3. Use if/else expressions for value selection instead of `||`.

Example fix

// before (BAML)
let enabled = userSetting || true;
// after
let enabled = (userSetting != null) || true;
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure left operand of || is bool
if (typeof leftOperand !== 'boolean') throw new Error('left operand of || must be bool');

Type guard

const isBool = (v) => typeof v === 'boolean';

Try / catch

try {
  result = evaluate(expr);
} catch (e) {
  if (String(e).includes('left operand of || must be bool')) {
    result = evaluate(expr.replace(leftSrc, `(${leftSrc} != null)`));
  } else throw e;
}

Prevention

When it happens

Trigger: Evaluating `a || b` where `a` is a string, int, null, list, or map — e.g. `configValue || defaultFlag`, `0 || true`, `null || cond`.

Common situations: JS/Python truthy-or-default patterns ported to BAML; variables expected to hold comparison results but holding raw config/LLM output values.

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/b02460d3b226ef2b. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-compiler/src/thir/interpret.rs:2488

            BamlValueWithMeta::Bool(greater_eq, meta.clone())
        }

        // Logical operations
        BinaryOperator::And => match left_val.clone() {
            BamlValueWithMeta::Bool(false, _) => BamlValueWithMeta::Bool(false, meta.clone()),
            BamlValueWithMeta::Bool(true, _) => match right_val.clone() {
                BamlValueWithMeta::Bool(b, _) => BamlValueWithMeta::Bool(b, meta.clone()),
                _ => bail!("right operand of && must be bool at {:?}", meta.0),
            },
            _ => bail!("left operand of && must be bool at {:?}", meta.0),
        },
        BinaryOperator::Or => match left_val.clone() {
            BamlValueWithMeta::Bool(true, _) => BamlValueWithMeta::Bool(true, meta.clone()),
            BamlValueWithMeta::Bool(false, _) => match right_val.clone() {
                BamlValueWithMeta::Bool(b, _) => BamlValueWithMeta::Bool(b, meta.clone()),
                _ => bail!("right operand of || must be bool at {:?}", meta.0),
            },
            _ => bail!("left operand of || must be bool at {:?}", meta.0),
        },

        // Bitwise operations (integer only)
        BinaryOperator::BitAnd => match (left_val.clone(), right_val.clone()) {
            (BamlValueWithMeta::Int(a, _), BamlValueWithMeta::Int(b, _)) => {
                BamlValueWithMeta::Int(a & b, meta.clone())
            }
            _ => bail!("bitwise & requires integer operands at {:?}", meta.0),
        },
        BinaryOperator::BitOr => match (left_val.clone(), right_val.clone()) {
            (BamlValueWithMeta::Int(a, _), BamlValueWithMeta::Int(b, _)) => {
                BamlValueWithMeta::Int(a | b, meta.clone())
            }
            _ => bail!("bitwise | requires integer operands at {:?}", meta.0),
        },
        BinaryOperator::BitXor => match (left_val.clone(), right_val.clone()) {
            (BamlValueWithMeta::Int(a, _), BamlValueWithMeta::Int(b, _)) => {
                BamlValueWithMeta::Int(a ^ b, meta.clone())

View on GitHub (pinned to bd85ce9dee)