BoundaryML/baml · error
split() method only available on strings at {:?}
Error message
split() method only available on strings at {:?} What it means
The "split" string method is only defined for string receivers. When evaluate_method_call dispatches "split" it first pattern-matches the receiver as BamlValueWithMeta::String; any other receiver type (int, list, map, null, ...) triggers this bail. It exists because split(delimiter) has no meaning on non-string values in BAML's interpreter.
Source
Thrown at engine/baml-compiler/src/thir/interpret.rs:2930
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())
.map(|part| BamlValueWithMeta::String(part.to_string(), meta.clone()))
.collect();
Ok(BamlValueWithMeta::List(parts, meta.clone()))
}
"substring" => {
let BamlValueWithMeta::String(s, _) = receiver else {
bail!(
"substring() method only available on strings at {:?}",
meta.0View on GitHub (pinned to bd85ce9dee)
Solutions
- Check the receiver's actual type at the failing expression and make it a string first (explicit conversion or upstream type annotation fix).
- If the value is already a list, drop the split call entirely — no delimiter-based splitting is needed.
- Guard with a type check before calling split when the receiver type is dynamic.
Example fix
// before (items is already a list)
let parts = items.split(",");
// after
let parts = items; Defensive patterns
Strategy: type-guard
Validate before calling
// guard the receiver before split
if (v is string) {
return v.split(",");
} else if (v is string[]) {
return v;
} Type guard
fn is_string(v: BamlValue) -> bool { matches!(v, BamlValue::String(_)) } Try / catch
match result {
Err(e) if e.to_string().contains("split() method only available on strings") => default_split_result,
other => other,
} Prevention
- Check whether the value is already a list — splitting a list is a common mistake.
- Type-annotate extraction outputs as string when text is expected.
- Handle null from optional fields before calling string methods.
When it happens
Trigger: Calling <non-string>.split(",") in a BAML expression, e.g. splitting a number or a list, or splitting a value that is null at runtime.
Common situations: Values returned from LLM extraction typed as numbers/lists but assumed to be strings; splitting the result of an expression that actually returns a list already; null values from optional fields being split.
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
- endsWith() 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/e98d134c76f7e33a.
Report an issue: GitHub.