BoundaryML/baml · error
- operator requires numeric operand at
Error message
- operator requires numeric operand at {:?} What it means
Thrown when the unary minus `-` operator is applied to a value that is neither an Int nor a Float at runtime. The interpreter implements Neg only for numeric BamlValue variants; strings, bools, nulls, and collections hit the bail. There is no implicit numeric coercion in BAML expressions.
Solutions
- Ensure the operand is numeric; convert string numbers at the source (parse to int/float when deserializing)
- Annotate the variable as int or float so the typechecker rejects non-numeric values
- Guard with a null/type check before negating optional values
- If the string holds a number, change the field's declared type from string to int/float in the schema
Example fix
// before (BAML) let offset = -threshold; // threshold: string // after let offset = -(threshold as int); // or declare threshold as int
Defensive patterns
Strategy: type-guard
Validate before calling
// ensure numeric operand before unary minus
if (typeof v !== 'number') {
throw new Error(`- requires numeric operand, got ${typeof v}`);
} Type guard
const isNumber = (v: unknown): v is number => typeof v === 'number' && !Number.isNaN(v);
Try / catch
try {
result = evaluate(expr);
} catch (e) {
if (String(e).includes('- operator requires numeric operand')) {
// parse string to number at the source
}
throw e;
} Prevention
- Type numeric config fields as int/float, not string
- Parse JSON numbers into numeric-typed fields
- Check for null/undefined before negation
When it happens
Trigger: Evaluating `-x` where `x` is a string (e.g. a numeric string from JSON or user input), a bool, null, or a media/class value. Frequently when a number arrives as a string via JSON deserialization into a String-typed field.
Common situations: Negating a value parsed from text/json where the declared type is string, applying negation to a config value read as string, or a typo where the operand was reassigned to a non-numeric type.
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
- ! operator requires boolean operand at
- array assignment index out of bounds
- array assignment on non-list value at
- array assignment requires a non-negative integer index at
- assign to undeclared variable
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/d203026007b05954.
Report an issue: GitHub.
Appendix: source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2551
},
})
}
fn evaluate_unary_op(
operator: &crate::hir::UnaryOperator,
val: &BamlValueWithMeta<ExprMetadata>,
meta: &ExprMetadata,
) -> Result<BamlValueWithMeta<ExprMetadata>> {
use crate::hir::UnaryOperator;
Ok(match operator {
UnaryOperator::Not => match val.clone() {
BamlValueWithMeta::Bool(b, _) => BamlValueWithMeta::Bool(!b, meta.clone()),
_ => bail!("! operator requires boolean operand at {:?}", meta.0),
},
UnaryOperator::Neg => match val.clone() {
BamlValueWithMeta::Int(i, _) => BamlValueWithMeta::Int(-i, meta.clone()),
BamlValueWithMeta::Float(f, _) => BamlValueWithMeta::Float(-f, meta.clone()),
_ => bail!("- operator requires numeric operand at {:?}", meta.0),
},
})
}
fn values_equal(
left: &BamlValueWithMeta<ExprMetadata>,
right: &BamlValueWithMeta<ExprMetadata>,
) -> bool {
match (left, right) {
(BamlValueWithMeta::Int(a, _), BamlValueWithMeta::Int(b, _)) => a == b,
(BamlValueWithMeta::Float(a, _), BamlValueWithMeta::Float(b, _)) => a == b,
(BamlValueWithMeta::Int(a, _), BamlValueWithMeta::Float(b, _)) => *a as f64 == *b,
(BamlValueWithMeta::Float(a, _), BamlValueWithMeta::Int(b, _)) => *a == *b as f64,
(BamlValueWithMeta::String(a, _), BamlValueWithMeta::String(b, _)) => a == b,
(BamlValueWithMeta::Null(_), BamlValueWithMeta::Null(_)) => true,
_ => false,
}
}View on GitHub (pinned to bd85ce9dee)