{"record":{"id":"08b8750d56042a31","repo":"BoundaryML/baml","slug":"failed-to-parse-template","errorCode":null,"errorMessage":"Failed to parse template '{}': {}","messagePattern":"Failed to parse template '(.+?)': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"engine/baml-lib/baml-core/src/ir/ir_helpers/mod.rs","lineNumber":2082,"sourceCode":"                    .map(|i| i.name.as_str())\n                    .collect::<Vec<_>>()\n                    .join(\", \");\n                format!(\n                    \"{{% macro {name}({args}) %}}{template}{{% endmacro %}}\",\n                    name = t.name(),\n                    args = args_str,\n                    template = t.template(),\n                )\n            })\n            .chain(std::iter::once(template_content.to_string()))\n            .collect::<Vec<_>>()\n            .join(\"\\n\");\n\n        // Use the shared environment (trim_blocks, lstrip_blocks, debug,\n        // null formatter, regex_match/sum filters) to match the prompt renderer.\n        let mut env = get_env();\n        env.add_template(\"__template__\", &full_template)\n            .map_err(|e| anyhow::anyhow!(\"Failed to parse template '{}': {}\", name, e))?;\n\n        let tmpl = env\n            .get_template(\"__template__\")\n            .map_err(|e| anyhow::anyhow!(\"Failed to get template '{}': {}\", name, e))?;\n\n        let context = minijinja::Value::from_serialize(&args_map);\n        let rendered = tmpl\n            .render(context)\n            .map_err(|e| anyhow::anyhow!(\"Failed to render template '{}': {}\", name, e))?;\n\n        Ok(rendered)\n    }\n}\n\n#[cfg(test)]\nmod render_template_tests {\n    use baml_types::TemplateStringRenderer;\n    use repr::make_test_ir;","sourceCodeStart":2064,"sourceCodeEnd":2100,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/baml-core/src/ir/ir_helpers/mod.rs#L2064-L2100","documentation":"`render_template` assembles all template_strings as minijinja macros plus the target template, then registers the combined source with `env.add_template`. If minijinja's parser rejects the source (syntax error, bad expression, unknown construct), the failure is wrapped as 'Failed to parse template <name>: <minijinja error>'.","triggerScenarios":"Rendering a BAML template_string whose body contains invalid Jinja syntax — unbalanced {% %}, unknown filters/tags not registered in get_env(), malformed {{ expr }} — encountered during test argument evaluation.","commonSituations":"Copy-pasting Jinja2 features minijinja doesn't support; typos in expressions or filter names; an edit to one template_string breaking the concatenated macro source; version differences in minijinja filter availability (regex_match/sum).","solutions":["Fix the Jinja syntax reported by the wrapped minijinja error (it follows the template name in the message)","Check the template_string body in .baml for unbalanced blocks/braces and unsupported tags","Only use filters available in the shared env (e.g. regex_match, sum) or register custom ones","Render a minimal version of the template to isolate which line/expression fails to parse"],"exampleFix":"// before (.baml)\ntemplate_string T(x: string) #\"{{ x | nonexistent_filter }}\"#\n\n// after (.baml)\ntemplate_string T(x: string) #\"{{ x | upper }}\"#","handlingStrategy":"try-catch","validationCode":"// Basic pre-check before rendering\nfunction looksLikeBalancedJinja(src: string): boolean {\n  const open = (src.match(/{%/g) || []).length, close = (src.match(/%}/g) || []).length;\n  const openE = (src.match(/{{/g) || []).length, closeE = (src.match(/}}/g) || []).length;\n  return open === close && openE === closeE;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const rendered = render_template(name, args);\n} catch (e) {\n  if (String(e).startsWith('Failed to parse template')) {\n    console.error('Invalid Jinja in template_string; check blocks/filters:', e);\n  }\n  throw e;\n}","preventionTips":["Keep template_string bodies to minijinja-supported syntax and filters","Check block/tag balance after editing templates","Render templates in CI tests to catch parse errors early","Avoid Jinja2-only features and unregistered custom filters"],"tags":["rust","baml","template-string","jinja","parse-error"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}