BoundaryML/baml · error
includes() method only available on strings at
Error message
includes() method only available on strings at {:?} What it means
includes() performs a substring containment check and is defined only for string receivers in the BAML interpreter. If the receiver is not a string, evaluate_method_call bails with this error before the containment check runs.
Solutions
- Convert the receiver to a string before calling includes(), if string containment was intended.
- For arrays/lists, use the appropriate list membership expression instead of includes() (BAML's includes is string-only).
- Add a type check/branch on the receiver before calling includes().
- Use the error span to identify the receiver expression and correct its type.
Example fix
// before
let found = tags.includes("admin"); // tags is a list
// after
let found = "{{ tags }}".includes("admin"); // or use list membership Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof receiver !== 'string') {
throw new Error('includes() receiver must be a string; use list membership for arrays');
} Type guard
const isStr = (v) => typeof v === 'string';
Try / catch
try {
const res = await b.Function(args);
} catch (e) {
if (String(e.message).includes('includes() method only available on strings')) {
// switch to string coercion or list membership expression
}
throw e;
} Prevention
- Do not assume BAML's includes() works on arrays like JavaScript's Array.includes.
- Use list membership syntax for container containment checks.
- Stringify values before containment checks when types vary.
- Verify receiver types whenever refactoring expression blocks.
When it happens
Trigger: Calling `x.includes(sub)` where `x` is a non-string value — an array, map, int, bool, or null — expecting JavaScript-like behavior on arrays or other containers.
Common situations: Devs familiar with JavaScript's Array.prototype.includes call it on a BAML array/list; checking containment in a map value that isn't a string; a variable inferred as non-string at runtime though the code assumed 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
- startsWith() method only available on strings at
- toUpperCase() method only available on strings at
- trim() method only available on strings at
- array assignment on non-list value at
- bitwise ^= requires integer operands
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/97b67e56379c1ac4.
Report an issue: GitHub.
Appendix: source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2873
bail!("toUpperCase() method takes no arguments at {:?}", meta.0);
}
Ok(BamlValueWithMeta::String(s.to_uppercase(), meta.clone()))
}
"trim" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!("trim() method only available on strings at {:?}", meta.0);
};
if !args.is_empty() {
bail!("trim() method takes no arguments at {:?}", meta.0);
}
Ok(BamlValueWithMeta::String(
s.trim().to_string(),
meta.clone(),
))
}
"includes" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!(
"includes() method only available on strings at {:?}",
meta.0
);
};
if args.len() != 1 {
bail!("includes() method takes exactly 1 argument at {:?}", meta.0);
}
let BamlValueWithMeta::String(search, _) = &args[0] else {
bail!("includes() argument must be a string at {:?}", meta.0);
};
Ok(BamlValueWithMeta::Bool(
s.contains(search.as_str()),
meta.clone(),
))
}
"startsWith" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!(View on GitHub (pinned to bd85ce9dee)