BoundaryML/baml · error

Expected integer, got {}

Error message

Expected integer, got {}

What it means

Thrown during JSON-to-BAML conversion when a JSON number cannot be represented as an i64 integer for a BamlValue::Int target. The value's declared BAML type is Int, but the JSON number is fractional (e.g. 3.14) or exceeds the i64 range. json_to_baml is strict: it will not silently truncate or wrap.

Source

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

    fn json_to_baml(
        json: &serde_json::Value,
        target_type: &TypeIR,
        meta: &ExprMetadata,
    ) -> Result<BamlValueWithMeta<ExprMetadata>> {
        use baml_types::TypeIR;
        use serde_json::Value as JsonValue;

        match (json, target_type) {
            (JsonValue::Null, _) => Ok(BamlValueWithMeta::Null(meta.clone())),
            (JsonValue::Bool(b), TypeIR::Primitive(baml_types::TypeValue::Bool, _)) => {
                Ok(BamlValueWithMeta::Bool(*b, meta.clone()))
            }
            (JsonValue::Number(n), TypeIR::Primitive(baml_types::TypeValue::Int, _)) => {
                if let Some(i) = n.as_i64() {
                    Ok(BamlValueWithMeta::Int(i, meta.clone()))
                } else {
                    bail!("Expected integer, got {}", n)
                }
            }
            (JsonValue::Number(n), TypeIR::Primitive(baml_types::TypeValue::Float, _)) => {
                if let Some(f) = n.as_f64() {
                    Ok(BamlValueWithMeta::Float(f, meta.clone()))
                } else {
                    bail!("Expected float, got {}", n)
                }
            }
            (JsonValue::String(s), TypeIR::Primitive(baml_types::TypeValue::String, _)) => {
                Ok(BamlValueWithMeta::String(s.clone(), meta.clone()))
            }
            (JsonValue::Array(arr), TypeIR::List(elem_type, _)) => {
                let mut baml_list = Vec::new();
                for item in arr {
                    baml_list.push(json_to_baml(item, elem_type, meta)?);
                }
                Ok(BamlValueWithMeta::List(baml_list, meta.clone()))

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Change the declared BAML type of the field from int to float if fractional values are expected
  2. Clamp/round the JSON value to an integer before feeding it to the converter (e.g. Math.round, truncate)
  3. Verify the numeric value fits in a 64-bit signed integer; use string or float typing for larger magnitudes
  4. Inspect the JSON payload at the failing path and fix the upstream producer to emit integral numbers

Example fix

// before (schema)
score int
// JSON: {"score": 0.87}
// after (schema)
score float  // or round before: Math.round(0.87) => 1
Defensive patterns

Strategy: validation

Validate before calling

function ensureInt(n: unknown): number {
  if (typeof n !== 'number' || !Number.isInteger(n) || n > Number.MAX_SAFE_INTEGER) {
    throw new Error(`Expected integer, got ${n}`);
  }
  return n;
}
// run over JSON payload fields typed as int before conversion

Try / catch

try {
  value = parseJsonToBamlValue(json, schema);
} catch (e) {
  if (String(e).startsWith('Expected integer')) {
    // round/fix the offending field or change schema to float
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling parse_json_to_baml_value / json_to_baml with a TypeIR of Int and JSON input like `1.5`, `1e30`, or a huge number beyond 2^63-1. Recursive calls via json_to_baml hit the same bail for nested fields.

Common situations: Feeding LLM-produced JSON with float values (e.g. `"score": 0.87`) into a schema declaring `int`, or passing timestamps in milliseconds as large numbers that overflow i64 in exotic formats.

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