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
- Change the declared BAML type of the field from int to float if fractional values are expected
- Clamp/round the JSON value to an integer before feeding it to the converter (e.g. Math.round, truncate)
- Verify the numeric value fits in a 64-bit signed integer; use string or float typing for larger magnitudes
- 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
- Match schema types to actual JSON value kinds (float vs int)
- Round/truncate LLM-emitted numbers before conversion
- Validate numeric ranges (i64) of incoming payloads
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
- baml.json.deserialize failed: {e:?}
- Expected float, got {}
- type `{ty}` can't be passed through auto-CLI; deliver it via
- --json-args must be a JSON object, got: {json}
- missing required argument `{name}` (type: {ty}). pass it via
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/eadb171d9ab640a5.
Report an issue: GitHub.