BoundaryML/baml · error
replace() method only available on strings at {:?}
Error message
replace() method only available on strings at {:?} What it means
The BAML interpreter's evaluate_method_call hit the "replace" string method with a receiver value that is not a String. The library only defines replace() on string values, so it bails with the source location (meta.0) attached. This is a runtime type mismatch between the declared/actual receiver type and the method called.
Source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2974
}
let BamlValueWithMeta::Int(start, _) = &args[0] else {
bail!("substring() start argument must be an int at {:?}", meta.0);
};
let BamlValueWithMeta::Int(end, _) = &args[1] else {
bail!("substring() end argument must be an int at {:?}", meta.0);
};
let start = (*start as usize).min(s.len());
let end = (*end as usize).min(s.len()).max(start);
Ok(BamlValueWithMeta::String(
s[start..end].to_string(),
meta.clone(),
))
}
"replace" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!("replace() method only available on strings at {:?}", meta.0);
};
if args.len() != 2 {
bail!("replace() method takes exactly 2 arguments at {:?}", meta.0);
}
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" => {View on GitHub (pinned to bd85ce9dee)
Solutions
- Check the receiver's actual value/type at that source span and ensure it is a string before calling .replace()
- Add a type annotation or cast so the value is statically a string (e.g. coalesce null to "" or use string interpolation)
- If the value can be non-string, branch on its type or use a checked conversion instead of calling the method unconditionally
Example fix
// before (value may be int/null)
let cleaned = value.replace("-", "_");
// after
let cleaned = value.ToString().replace("-", "_"); Defensive patterns
Strategy: type-guard
Validate before calling
// before calling .replace
if (value != null && value is string) { value.replace("a","b"); } Type guard
fn is_string(v: Value) -> bool { matches!(v, Value::String(_)) } Try / catch
try { formatted = value.replace(search, repl); } catch (e) { log(e); formatted = null; } Prevention
- Annotate LLM output fields as string when you intend string ops
- Coalesce nullable fields before method calls
- Avoid calling string methods on array/map/number values
When it happens
Trigger: Calling .replace(...) on a non-string value at runtime, e.g. on an int, float, bool, null, map, or array — typically when the receiver came from an LLM response field, a media() result, or a variable whose type the typechecker did not constrain.
Common situations: Prompting an LLM that returns a number or null where the developer assumed a string, then calling .replace() on it inside a BAML expression; iterating mixed-type arrays and calling string methods on elements.
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.serialize returned non-string value: {other:?}
- endsWith() method only available on strings at {:?}
- split() method only available on strings at {:?}
- substring() method only available on strings at {:?}
- replace() method takes exactly 2 arguments at {:?}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/d5310b28fe20fe8b.
Report an issue: GitHub.