BoundaryML/baml · error

to_fixed() method only available on floats and ints at {:?}

Error message

to_fixed() method only available on floats and ints at {:?}

What it means

The "to_fixed" method formats a number to fixed decimal places and is only defined on Float and Int receivers. The interpreter bails when the receiver is any other value type, attaching the source span. Ints are accepted and widened to f64.

Source

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

            }
            let BamlValueWithMeta::String(search, _) = &args[0] else {
                bail!("replace() search argument must be a string at {:?}", meta.0);
            };
            let BamlValueWithMeta::String(replacement, _) = &args[1] else {
                bail!(
                    "replace() replacement argument must be a string at {:?}",
                    meta.0
                );
            };
            // Replace first occurrence only (matching JavaScript behavior)
            let result = s.replacen(search.as_str(), replacement.as_str(), 1);
            Ok(BamlValueWithMeta::String(result, meta.clone()))
        }
        "to_fixed" => {
            let value = match receiver {
                BamlValueWithMeta::Float(v, _) => *v,
                BamlValueWithMeta::Int(v, _) => *v as f64,
                _ => bail!(
                    "to_fixed() method only available on floats and ints at {:?}",
                    meta.0
                ),
            };

            if args.len() > 1 {
                bail!("to_fixed() method takes at most 1 argument at {:?}", meta.0);
            }

            let digits = match args.first() {
                Some(BamlValueWithMeta::Int(v, _)) => *v,
                Some(_) => bail!("to_fixed() digits argument must be an int at {:?}", meta.0),
                None => 0,
            };

            let formatted = baml_vm::native::number_to_fixed(value, digits)
                .map_err(|msg| anyhow::anyhow!("{msg} at {:?}", meta.0))?;
            Ok(BamlValueWithMeta::String(formatted, meta.clone()))

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Ensure the receiver is a number: parse the string to a float/int first if it is numeric text
  2. Annotate the variable as float/int so the typechecker enforces it
  3. Guard against null by coalescing to a default number before formatting

Example fix

// before (value is a string)
let out = price.to_fixed(2);
// after
let out = price.ToFloat().to_fixed(2);
Defensive patterns

Strategy: type-guard

Validate before calling

// receiver must be number: if (v is int || v is float) { v.to_fixed(2); }

Type guard

fn is_number(v: Value) -> bool { matches!(v, Value::Int(_) | Value::Float(_)) }

Try / catch

try { out = v.to_fixed(2); } catch (e) { out = null; log(e); }

Prevention

When it happens

Trigger: Calling .to_fixed(...) on a string, bool, null, map, array, or media value — commonly when the receiver is a numeric-looking string like "3.14159" from an LLM response.

Common situations: LLM returns numbers as strings in JSON mode; developer assumes the value is numeric and calls to_fixed on it; iterating heterogeneous arrays and formatting every element.

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