BoundaryML/baml · error
endsWith() argument must be a string at {:?}
Error message
endsWith() argument must be a string at {:?} What it means
The endsWith method's single argument must be a string. The interpreter destructures args[0] as BamlValueWithMeta::String and bails with this message if it is an int, bool, list, or other value type. The library throws it rather than coercing non-string arguments.
Source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2921
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);
};
if args.len() != 1 {
bail!("split() method takes exactly 1 argument at {:?}", meta.0);
}
let BamlValueWithMeta::String(delimiter, _) = &args[0] else {
bail!("split() argument must be a string at {:?}", meta.0);
};
let parts: Vec<BamlValueWithMeta<ExprMetadata>> = s
.split(delimiter.as_str())View on GitHub (pinned to bd85ce9dee)
Solutions
- Convert the argument to a string (e.g. use .to_string() on the value or a string literal) before passing it to endsWith.
- Verify the type of the expression passed as the argument at the failing call site.
- Add a type guard around the call if the argument can be a non-string at runtime.
Example fix
// before let ok = s.endsWith(version); // version: int // after let ok = s.endsWith(version.to_string());
Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the suffix argument is a string before the call // suffix must be string: literal or converted value
Type guard
fn is_string(v: BamlValue) -> bool { matches!(v, BamlValue::String(_)) } Try / catch
match result {
Err(e) if e.to_string().contains("argument must be a string") => use_default_suffix,
other => other,
} Prevention
- Quote suffix literals instead of passing raw numbers.
- Convert numeric/enum values with to_string() before using them as method arguments.
- Keep suffix values in string-typed variables.
When it happens
Trigger: Calling s.endsWith(5), s.endsWith(myIntVar), s.endsWith(null), or passing a list/bool as the suffix in a BAML expression.
Common situations: Numeric literals or extracted numeric values passed as the suffix without conversion; variables from structured extraction that are not strings; typos where an int variable shadows the intended string.
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() argument must be a string at {:?}
- endsWith() method only available on strings at {:?}
- split() method only available on strings at {:?}
- substring() method only available on strings at {:?}
- type `{ty}` can't be passed through auto-CLI; deliver it via
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/3ad2025e2e57c39d.
Report an issue: GitHub.