BoundaryML/baml · error
endsWith() method only available on strings at {:?}
Error message
endsWith() method only available on strings at {:?} What it means
The BAML expression interpreter evaluates the "endsWith" string method at runtime. Before calling ends_with on the receiver it pattern-matches it as a String value; if the receiver is any other type (int, list, map, null, etc.) it bails with this message. The library throws it because endsWith is only defined for string receivers, and static typing did not catch the mismatch.
Source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2912
);
};
if args.len() != 1 {
bail!(
"startsWith() method takes exactly 1 argument at {:?}",
meta.0
);
}
let BamlValueWithMeta::String(prefix, _) = &args[0] else {
bail!("startsWith() argument must be a string at {:?}", meta.0);
};
Ok(BamlValueWithMeta::Bool(
s.starts_with(prefix.as_str()),
meta.clone(),
))
}
"endsWith" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!(
"endsWith() method only available on strings at {:?}",
meta.0
);
};
if args.len() != 1 {
bail!("endsWith() method takes exactly 1 argument at {:?}", meta.0);
}
let BamlValueWithMeta::String(suffix, _) = &args[0] else {
bail!("endsWith() argument must be a string at {:?}", meta.0);
};
Ok(BamlValueWithMeta::Bool(
s.ends_with(suffix.as_str()),
meta.clone(),
))
}
"split" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!("split() method only available on strings at {:?}", meta.0);View on GitHub (pinned to bd85ce9dee)
Solutions
- Inspect the receiver value at the failing expression and confirm its actual type (print it or check the type annotation in the BAML file).
- Convert the receiver to a string explicitly before calling endsWith, or fix the upstream expression so it yields a string.
- If the receiver may legitimately be non-string, guard the call with a type check (e.g. `x is string` / match on the type) before invoking endsWith.
- Check whether type annotations on the variable are wrong so the compiler can catch this statically instead of at runtime.
Example fix
// before (x is an int)
let flag = x.endsWith("5");
// after
let flag = x.to_string().endsWith("5"); Defensive patterns
Strategy: type-guard
Validate before calling
// in BAML expression code, before the call
if (x is string) {
return x.endsWith("suffix");
} Type guard
fn is_string(v: BamlValue) -> bool { matches!(v, BamlValue::String(_)) } Try / catch
// interpreter-level: handle the bail
match evaluate_method_call(...) {
Ok(v) => v,
Err(e) if e.to_string().contains("only available on strings") => fallback_value,
Err(e) => return Err(e),
} Prevention
- Annotate variables with explicit string types so the compiler catches non-string receivers.
- Never call string methods on values returned from untyped extraction blocks without checking the type.
- Print or log the value once when wiring up a new expression to confirm its runtime type.
When it happens
Trigger: Calling <non-string>.endsWith(...) in a BAML expression, e.g. `let x = 5; x.endsWith("5")` or `myList.endsWith("a")`, where the receiver's value is not BamlValueWithMeta::String when evaluate_method_call runs.
Common situations: Variables assumed to be strings but actually produced by a prompt/extraction block as a number or list; refactors that change a variable's type without updating downstream method calls; dynamic values from maps or function results that are null or untyped at runtime.
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
- split() method only available on strings at {:?}
- substring() method only available on strings at {:?}
- baml.json.serialize returned non-string value: {other:?}
- endsWith() argument must be a string at {:?}
- split() argument must be a string at {:?}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e9fe1041825dae0c.
Report an issue: GitHub.