BoundaryML/baml · error · minijinja::Error
TooManyArguments
TooManyArguments
Error message
role() called with two roles: '{a}' and '{b}' What it means
BAML's `role()` template function accepts a role either positionally — `role('assistant')` — or as a keyword — `role(role='assistant')`. Supplying both makes the intent ambiguous, so the function immediately returns a TooManyArguments error naming both conflicting roles.
Source
Thrown at engine/baml-lib/jinja-runtime/src/lib.rs:334
for (enum_name, enum_values) in enum_values_by_name {
env.add_global(
enum_name.clone(),
minijinja::value::Value::from_object(MinijinjaBamlEnumType {
enum_name,
enum_values: enum_values
.into_iter()
.map(|v| (v.value.clone(), v))
.collect(),
}),
);
}
let role_fn = minijinja::Value::from_function(
|role: Option<String>, kwargs: Kwargs| -> Result<String, minijinja::Error> {
let role = match (role, kwargs.get::<String>("role")) {
(Some(b), Ok(a)) => {
// If both are present, we should error
return Err(minijinja::Error::new(
ErrorKind::TooManyArguments,
format!("role() called with two roles: '{a}' and '{b}'"),
));
}
(Some(role), _) => role,
(_, Ok(role)) => role,
_ => {
// If neither are present, we should error
return Err(minijinja::Error::new(
ErrorKind::MissingArgument,
"role() called without role. Try role('role') or role(role='role').",
));
}
};
let allow_duplicate_role = match kwargs.get::<bool>("__baml_allow_dupe_role__") {
Ok(allow_duplicate_role) => allow_duplicate_role,
Err(e) => match e.kind() {View on GitHub (pinned to bd85ce9dee)
Solutions
- Keep exactly one form: either `{{ role('assistant') }}` or `{{ role(role='assistant') }}`.
- If a macro/wrapper supplies the role positionally, remove the literal role= kwarg from the template (or vice versa).
- Search the template and any included macros for all role() call sites and unify the style.
Example fix
// before
{{ _.role('user', role='system') }}Message
// after
{{ _.role('user') }}Message Defensive patterns
Strategy: validation
Validate before calling
// reject role() calls mixing positional and kwarg forms during template linting const bad = /role\s*\(\s*['"][^'"]+['"]\s*,\s*role\s*=/;
Prevention
- Pick one call style project-wide: role('name') OR role(role='name').
- Grep templates and macros for all role( call sites in CI.
- In wrapper macros, pass the role exactly once.
When it happens
Trigger: A chat template calling `{{ role('user', role='system') }}` or a macro that injects a positional role while the template also passes the `role=` kwarg.
Common situations: Refactoring templates from positional to keyword style and leaving both; composable partial templates where a wrapper passes role positionally and the inner template adds role=; copy-paste merges of two role call styles.
Related errors
- MissingArgument
- Encountered impossible jinja expression during parsing
- Failed to parse template '{}': {}
- Failed to get template '{}': {}
- BamlImage has no callable attribute '{args:#?}'
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/96a8642fc03faece.
Report an issue: GitHub.